summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.hgtags1
-rwxr-xr-xBuildParams9
-rwxr-xr-xautobuild.xml144
-rwxr-xr-xindra/CMakeLists.txt6
-rwxr-xr-xindra/cmake/00-Common.cmake3
-rw-r--r--indra/cmake/CEFPlugin.cmake40
-rwxr-xr-xindra/cmake/CMakeLists.txt8
-rwxr-xr-xindra/cmake/Linking.cmake2
-rwxr-xr-xindra/cmake/Variables.cmake2
-rwxr-xr-xindra/cmake/WebKitLibPlugin.cmake93
-rwxr-xr-xindra/lib/python/indra/util/llmanifest.py56
-rwxr-xr-xindra/llplugin/CMakeLists.txt3
-rwxr-xr-xindra/llplugin/llpluginclassmedia.cpp279
-rwxr-xr-xindra/llplugin/llpluginclassmedia.h11
-rwxr-xr-xindra/llplugin/llpluginclassmediaowner.h2
-rwxr-xr-xindra/llplugin/llpluginprocesschild.cpp43
-rwxr-xr-xindra/llplugin/llpluginprocesschild.h7
-rwxr-xr-xindra/llplugin/llpluginprocessparent.cpp308
-rwxr-xr-xindra/llplugin/llpluginprocessparent.h28
-rwxr-xr-xindra/llplugin/slplugin/slplugin.cpp1
-rwxr-xr-xindra/llui/llfocusmgr.cpp18
-rwxr-xr-xindra/llui/llfocusmgr.h9
-rwxr-xr-xindra/llui/llview.cpp46
-rwxr-xr-xindra/llui/llview.h3
-rwxr-xr-xindra/llwindow/llkeyboardwin32.cpp4
-rw-r--r--indra/llwindow/llopenglview-objc.mm47
-rwxr-xr-xindra/llwindow/llwindowmacosx-objc.h24
-rwxr-xr-xindra/llwindow/llwindowmacosx.cpp84
-rwxr-xr-xindra/llwindow/llwindowwin32.cpp13
-rwxr-xr-xindra/llwindow/llwindowwin32.h5
-rwxr-xr-xindra/media_plugins/CMakeLists.txt9
-rw-r--r--[-rwxr-xr-x]indra/media_plugins/cef/CMakeLists.txt (renamed from indra/media_plugins/webkit/CMakeLists.txt)75
-rw-r--r--[-rwxr-xr-x]indra/media_plugins/cef/mac_volume_catcher.cpp (renamed from indra/media_plugins/webkit/mac_volume_catcher.cpp)2
-rw-r--r--indra/media_plugins/cef/media_plugin_cef.cpp885
-rw-r--r--[-rwxr-xr-x]indra/media_plugins/cef/volume_catcher.h (renamed from indra/media_plugins/webkit/volume_catcher.h)0
-rw-r--r--[-rwxr-xr-x]indra/media_plugins/cef/windows_volume_catcher.cpp (renamed from indra/media_plugins/webkit/windows_volume_catcher.cpp)0
-rwxr-xr-xindra/media_plugins/quicktime/CMakeLists.txt3
-rwxr-xr-xindra/media_plugins/quicktime/media_plugin_quicktime.cpp4
-rwxr-xr-xindra/media_plugins/webkit/dummy_volume_catcher.cpp58
-rwxr-xr-xindra/media_plugins/webkit/linux_volume_catcher.cpp468
-rwxr-xr-xindra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc21
-rwxr-xr-xindra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc6
-rwxr-xr-xindra/media_plugins/webkit/media_plugin_webkit.cpp1481
-rwxr-xr-xindra/media_plugins/winmmshim/CMakeLists.txt3
-rwxr-xr-xindra/newview/CMakeLists.txt64
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rwxr-xr-xindra/newview/app_settings/settings.xml108
-rwxr-xr-xindra/newview/llappviewer.cpp18
-rwxr-xr-xindra/newview/llfloaterpreference.cpp11
-rwxr-xr-xindra/newview/llfloatertos.cpp23
-rwxr-xr-xindra/newview/llmediactrl.cpp65
-rwxr-xr-xindra/newview/llmediactrl.h5
-rwxr-xr-xindra/newview/lltoolpie.cpp243
-rwxr-xr-xindra/newview/lltoolpie.h3
-rwxr-xr-xindra/newview/llviewerkeyboard.cpp5
-rwxr-xr-xindra/newview/llviewerkeyboard.h1
-rwxr-xr-xindra/newview/llviewermedia.cpp640
-rwxr-xr-xindra/newview/llviewermedia.h9
-rwxr-xr-xindra/newview/llviewermediafocus.cpp22
-rwxr-xr-xindra/newview/llviewermediafocus.h5
-rwxr-xr-xindra/newview/llviewerparcelmedia.cpp8
-rwxr-xr-xindra/newview/llviewerwindow.cpp65
-rwxr-xr-xindra/newview/llviewerwindow.h1
-rwxr-xr-xindra/newview/llweb.cpp4
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_tos.xml15
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_login.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_viewer.xml4
-rwxr-xr-xindra/newview/skins/default/xui/en/mime_types.xml40
-rwxr-xr-xindra/newview/skins/default/xui/en/mime_types_mac.xml38
-rwxr-xr-xindra/newview/skins/default/xui/en/notifications.xml17
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_preferences_setup.xml13
-rwxr-xr-xindra/newview/skins/default/xui/en/strings.xml2
-rwxr-xr-xindra/newview/tests/llmediadataclient_test.cpp2
-rwxr-xr-xindra/newview/viewer_manifest.py272
-rw-r--r--indra/test_apps/llfbconnecttest/CMakeLists.txt372
-rw-r--r--indra/test_apps/llfbconnecttest/README.Linden20
-rw-r--r--indra/test_apps/llfbconnecttest/bookmarks.txt4
-rw-r--r--indra/test_apps/llfbconnecttest/llfbconnecttest.cpp2394
-rw-r--r--indra/test_apps/llfbconnecttest/llfbconnecttest.h173
-rwxr-xr-xindra/test_apps/llplugintest/CMakeLists.txt277
-rwxr-xr-xindra/test_apps/llplugintest/llmediaplugintest.cpp2377
-rwxr-xr-xindra/test_apps/llplugintest/llmediaplugintest.h207
82 files changed, 2711 insertions, 9134 deletions
diff --git a/.hgtags b/.hgtags
index 0a97b4b9a5..5c4559b232 100755
--- a/.hgtags
+++ b/.hgtags
@@ -510,3 +510,4 @@ d07f76c5b9860fb87924d00ca729f7d4532534d6 3.7.29-release
27e3cf444c4cc645884960a61325a9ee0e9a2d0f 3.8.4-release
e821ef17c6edea4a59997719d8ba416d8c16e143 3.8.5-release
5a5bd148943bfb46cf2ff2ccf376c42dee93d19b 3.8.6-release
+ae3297cdd03ab14f19f3811acbc4acd3eb600336 4.0.0-release
diff --git a/BuildParams b/BuildParams
index 7aff447dda..0d3d1922e9 100755
--- a/BuildParams
+++ b/BuildParams
@@ -70,12 +70,15 @@ additional_packages = ""
# the viewer_channel_suffix is prefixed by a blank and then appended to the viewer_channel
# for the package in a setting that overrides the compiled-in value
################################################################
-additional_packages = "EDU"
+## Removed 2015-07-02 (MAINT-5360) until we fix packaging step in Team City
+## additional_packages = "EDU"
# The EDU package allows us to create a separate release channel whose expirations
# are synchronized as much as possible with the academic year
-EDU_sourceid = ""
-EDU_viewer_channel_suffix = "edu"
+## Removed 2015-07-02 (MAINT-5360) until we fix packaging step in Team City
+## EDU_sourceid = ""
+## Removed 2015-07-02 (MAINT-5360) until we fix packaging step in Team City
+## EDU_viewer_channel_suffix = "edu"
# Notifications - to configure email notices, add a setting like this:
# <username>_<reponame>.email = <email-address>
diff --git a/autobuild.xml b/autobuild.xml
index 7488b816ec..8cbe12dbf5 100755
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1463,16 +1463,18 @@
<key>version</key>
<string>0.0.1</string>
</map>
- <key>llphysicsextensions_source</key>
+ <key>llceflib</key>
<map>
<key>copyright</key>
- <string>Copyright (c) 2010, Linden Research, Inc.</string>
+ <string>Copyright (c) 2014, Linden Research, Inc.</string>
+ <key>description</key>
+ <string>LLCefLib implements a headless web browser, rendering modern web content to a memory buffer and providing an API for injecting mouse and keyboard events. It uses the Chromium Embedded Framework (https://bitbucket.org/chromiumembedded/cef)</string>
<key>license</key>
- <string>internal</string>
+ <string>LGPL</string>
<key>license_file</key>
- <string>LICENSES/llphysicsextensions.txt</string>
+ <string>LICENSES/LICENSE-source.txt</string>
<key>name</key>
- <string>llphysicsextensions_source</string>
+ <string>llceflib</string>
<key>platforms</key>
<map>
<key>darwin</key>
@@ -1480,44 +1482,34 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>468e88a527e610804c3eecf07f4ed70b</string>
+ <string>5a0f74f8e736d91d2c2c6cbc71db90bd</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions-source_llphysicsextensions-update/rev/298369/arch/Darwin/installer/llphysicsextensions_source-1.0.298369-darwin-298369.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/309177/arch/Darwin/installer/llceflib-1.5.1.309177-darwin-309177.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
</map>
- <key>linux</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>793964e49c935b414c4bdbb8a0d14ad1</string>
- <key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions-source_llphysicsextensions-update/rev/298369/arch/Linux/installer/llphysicsextensions_source-1.0.298369-linux-298369.tar.bz2</string>
- </map>
- <key>name</key>
- <string>linux</string>
- </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>922aad5261aac150e5ce3c094e57f373</string>
+ <string>5ed007e503cd768681ba282fd6d7aa76</string>
+ <key>hash_algorithm</key>
+ <string>md5</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions-source_llphysicsextensions-update/rev/298369/arch/CYGWIN/installer/llphysicsextensions_source-1.0.298369-windows-298369.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/309177/arch/CYGWIN/installer/llceflib-1.5.1.309177-windows-309177.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
</map>
<key>version</key>
- <string>1.0.298369</string>
+ <string>1.5.1.309177</string>
</map>
- <key>llphysicsextensions_stub</key>
+ <key>llphysicsextensions_source</key>
<map>
<key>copyright</key>
<string>Copyright (c) 2010, Linden Research, Inc.</string>
@@ -1526,7 +1518,7 @@
<key>license_file</key>
<string>LICENSES/llphysicsextensions.txt</string>
<key>name</key>
- <string>llphysicsextensions_stub</string>
+ <string>llphysicsextensions_source</string>
<key>platforms</key>
<map>
<key>darwin</key>
@@ -1534,11 +1526,11 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>1175977a191ffc936fd0ccca433c8278</string>
+ <string>468e88a527e610804c3eecf07f4ed70b</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions-stub_llphysicsextensions-update/rev/298370/arch/Darwin/installer/llphysicsextensions_stub-1.0.298370-darwin-298370.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions-source_llphysicsextensions-update/rev/298369/arch/Darwin/installer/llphysicsextensions_source-1.0.298369-darwin-298369.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
@@ -1548,9 +1540,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>d13d7927692eab2d6a63e36166b72a8a</string>
+ <string>793964e49c935b414c4bdbb8a0d14ad1</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions-stub_llphysicsextensions-update/rev/298370/arch/Linux/installer/llphysicsextensions_stub-1.0.298370-linux-298370.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions-source_llphysicsextensions-update/rev/298369/arch/Linux/installer/llphysicsextensions_source-1.0.298369-linux-298369.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
@@ -1560,29 +1552,27 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>9594f6fd79ee924fe675a4a23e30516e</string>
+ <string>922aad5261aac150e5ce3c094e57f373</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions-stub_llphysicsextensions-update/rev/298370/arch/CYGWIN/installer/llphysicsextensions_stub-1.0.298370-windows-298370.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions-source_llphysicsextensions-update/rev/298369/arch/CYGWIN/installer/llphysicsextensions_source-1.0.298369-windows-298369.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
</map>
<key>version</key>
- <string>1.0.298370</string>
+ <string>1.0.298369</string>
</map>
- <key>llqtwebkit</key>
+ <key>llphysicsextensions_stub</key>
<map>
<key>copyright</key>
- <string>Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).</string>
- <key>description</key>
- <string>QT cross-platform application and UI framework.</string>
+ <string>Copyright (c) 2010, Linden Research, Inc.</string>
<key>license</key>
- <string>LGPL</string>
+ <string>internal</string>
<key>license_file</key>
- <string>LICENSES/llqtwebkit.txt</string>
+ <string>LICENSES/llphysicsextensions.txt</string>
<key>name</key>
- <string>llqtwebkit</string>
+ <string>llphysicsextensions_stub</string>
<key>platforms</key>
<map>
<key>darwin</key>
@@ -1590,11 +1580,11 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>3c2b6be4c78b2479c3fae612e1053d37</string>
+ <string>1175977a191ffc936fd0ccca433c8278</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/canonical_3p-llqtwebkit2/rev/295522/arch/Darwin/installer/llqtwebkit-4.7.1-darwin-20141015.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions-stub_llphysicsextensions-update/rev/298370/arch/Darwin/installer/llphysicsextensions_stub-1.0.298370-darwin-298370.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
@@ -1604,11 +1594,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>d31358176b9ba8c676458cc061767c0b</string>
- <key>hash_algorithm</key>
- <string>md5</string>
+ <string>d13d7927692eab2d6a63e36166b72a8a</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/canonical_3p-llqtwebkit2/rev/295522/arch/Linux/installer/llqtwebkit-4.7.1-linux-20141015.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions-stub_llphysicsextensions-update/rev/298370/arch/Linux/installer/llphysicsextensions_stub-1.0.298370-linux-298370.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
@@ -1618,18 +1606,16 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>bb4e8c8006c8a7aef6d3e3c36a8cebbf</string>
- <key>hash_algorithm</key>
- <string>md5</string>
+ <string>9594f6fd79ee924fe675a4a23e30516e</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/canonical_3p-llqtwebkit2/rev/295522/arch/CYGWIN/installer/llqtwebkit-4.7.1-windows-20141015.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions-stub_llphysicsextensions-update/rev/298370/arch/CYGWIN/installer/llphysicsextensions_stub-1.0.298370-windows-298370.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
</map>
<key>version</key>
- <string>4.7.1</string>
+ <string>1.0.298370</string>
</map>
<key>mesa</key>
<map>
@@ -1998,9 +1984,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>3f8b52280cb1eff2d1acd0214bce1b16</string>
+ <string>78650a79bda6435e623a940ad425a593</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/quicktime_3p-update-quicktime/rev/296445/arch/CYGWIN/installer/quicktime-7.3-windows-296445.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/quicktime_3p-update-quicktime/rev/300073/arch/CYGWIN/installer/quicktime-7.3-windows-300073.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@@ -2009,62 +1995,6 @@
<key>version</key>
<string>7.3</string>
</map>
- <key>slplugins</key>
- <map>
- <key>copyright</key>
- <string>Second Life Viewer Source Code - Copyright (C) 2010, Linden Research, Inc.</string>
- <key>description</key>
- <string>Second Life Viewer Plugins and launcher</string>
- <key>license</key>
- <string>LGPL</string>
- <key>license_file</key>
- <string>LICENSES/slplugins-license.txt</string>
- <key>name</key>
- <string>slplugins</string>
- <key>platforms</key>
- <map>
- <key>darwin</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>f6bfb026572f03a4c8ac6b2b7d7eb0ae</string>
- <key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/slplugins_3p-update-slplugins/rev/298079/arch/Darwin/installer/slplugins-3.7.24.297623.298079-darwin-298079.tar.bz2</string>
- </map>
- <key>name</key>
- <string>darwin</string>
- </map>
- <key>linux</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>64b8a3bac95b5888a7ede3d7661a18b8</string>
- <key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/slplugins_3p-update-slplugins/rev/298079/arch/Linux/installer/slplugins-3.7.24.297623.298079-linux-298079.tar.bz2</string>
- </map>
- <key>name</key>
- <string>linux</string>
- </map>
- <key>windows</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>3a1ea3385303b78b0327c8cea929ef27</string>
- <key>hash_algorithm</key>
- <string>md5</string>
- <key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/slplugins_3p-update-slplugins/rev/298079/arch/CYGWIN/installer/slplugins-3.7.24.297623.298079-windows-298079.tar.bz2</string>
- </map>
- <key>name</key>
- <string>windows</string>
- </map>
- </map>
- <key>version</key>
- <string>3.7.24.297623.298079</string>
- </map>
<key>slvoice</key>
<map>
<key>copyright</key>
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index 10692402a5..133c5ee265 100755
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -57,12 +57,6 @@ add_subdirectory(${VIEWER_PREFIX}test)
if (ENABLE_MEDIA_PLUGINS)
# viewer media plugins
add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins)
-
- # llplugin testbed code (is this the right way to include it?)
- if (LL_TESTS AND NOT LINUX)
- add_subdirectory(${VIEWER_PREFIX}test_apps/llplugintest)
- add_subdirectory(${VIEWER_PREFIX}test_apps/llfbconnecttest)
- endif (LL_TESTS AND NOT LINUX)
endif (ENABLE_MEDIA_PLUGINS)
if (LINUX)
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 1a3b6c5117..86fc2dfff5 100755
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -166,6 +166,9 @@ if (LINUX)
-pthread
)
+ # force this platform to accept TOS via external browser
+ add_definitions(-DEXTERNAL_TOS)
+
add_definitions(-DAPPID=secondlife)
add_definitions(-fvisibility=hidden)
# don't catch SIGCHLD in our base application class for the viewer - some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The viewer doesn't need to catch SIGCHLD anyway.
diff --git a/indra/cmake/CEFPlugin.cmake b/indra/cmake/CEFPlugin.cmake
new file mode 100644
index 0000000000..9cfb7d14c7
--- /dev/null
+++ b/indra/cmake/CEFPlugin.cmake
@@ -0,0 +1,40 @@
+# -*- cmake -*-
+include(Linking)
+include(Prebuilt)
+
+if (USESYSTEMLIBS)
+ set(CEFPLUGIN OFF CACHE BOOL
+ "CEFPLUGIN support for the llplugin/llmedia test apps.")
+else (USESYSTEMLIBS)
+ use_prebuilt_binary(llceflib)
+ set(CEFPLUGIN ON CACHE BOOL
+ "CEFPLUGIN support for the llplugin/llmedia test apps.")
+ set(CEF_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/cef)
+endif (USESYSTEMLIBS)
+
+if (WINDOWS)
+ set(CEF_PLUGIN_LIBRARIES
+ libcef.lib
+ libcef_dll_wrapper.lib
+ llceflib.lib
+ )
+elseif (DARWIN)
+ FIND_LIBRARY(APPKIT_LIBRARY AppKit)
+ if (NOT APPKIT_LIBRARY)
+ message(FATAL_ERROR "AppKit not found")
+ endif()
+
+ FIND_LIBRARY(CEF_LIBRARY "Chromium Embedded Framework" ${ARCH_PREBUILT_DIRS_RELEASE})
+ if (NOT CEF_LIBRARY)
+ message(FATAL_ERROR "CEF not found")
+ endif()
+
+ set(CEF_PLUGIN_LIBRARIES
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libcef_dll_wrapper.a
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libLLCefLib.a
+ ${APPKIT_LIBRARY}
+ ${CEF_LIBRARY}
+ )
+
+elseif (LINUX)
+endif (WINDOWS)
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index d700c7fd99..04a2a16c27 100755
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -13,6 +13,7 @@ set(cmake_SOURCE_FILES
BerkeleyDB.cmake
Boost.cmake
BuildVersion.cmake
+ CEFPlugin.cmake
CMakeCopyIfDifferent.cmake
ConfigurePkgConfig.cmake
CURL.cmake
@@ -79,18 +80,18 @@ set(cmake_SOURCE_FILES
LLXML.cmake
LScript.cmake
Linking.cmake
-## MediaPluginBase.cmake
+ MediaPluginBase.cmake
NDOF.cmake
OPENAL.cmake
OpenGL.cmake
OpenJPEG.cmake
OpenSSL.cmake
PNG.cmake
-## PluginAPI.cmake
+ PluginAPI.cmake
Prebuilt.cmake
PulseAudio.cmake
Python.cmake
-## QuickTimePlugin.cmake
+ QuickTimePlugin.cmake
TemplateCheck.cmake
Tut.cmake
UI.cmake
@@ -99,7 +100,6 @@ set(cmake_SOURCE_FILES
Variables.cmake
ViewerMiscLibs.cmake
VisualLeakDetector.cmake
-## WebKitLibPlugin.cmake
XmlRpcEpi.cmake
ZLIB.cmake
)
diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake
index c95f0c3702..74fe3f1137 100755
--- a/indra/cmake/Linking.cmake
+++ b/indra/cmake/Linking.cmake
@@ -6,7 +6,7 @@ set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES")
include(Variables)
set(ARCH_PREBUILT_DIRS ${AUTOBUILD_INSTALL_DIR}/lib)
-##set(ARCH_PREBUILT_DIRS_PLUGINS ${AUTOBUILD_INSTALL_DIR}/plugins)
+set(ARCH_PREBUILT_DIRS_PLUGINS ${AUTOBUILD_INSTALL_DIR}/plugins)
set(ARCH_PREBUILT_DIRS_RELEASE ${AUTOBUILD_INSTALL_DIR}/lib/release)
set(ARCH_PREBUILT_DIRS_DEBUG ${AUTOBUILD_INSTALL_DIR}/lib/debug)
if (WINDOWS)
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index 2fb47c58a7..63e296b556 100755
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -26,7 +26,7 @@ set(VIEWER_PREFIX)
set(INTEGRATION_TESTS_PREFIX)
set(LL_TESTS ON CACHE BOOL "Build and run unit and integration tests (disable for build timing runs to reduce variation")
set(INCREMENTAL_LINK OFF CACHE BOOL "Use incremental linking on win32 builds (enable for faster links on some machines)")
-set(ENABLE_MEDIA_PLUGINS OFF CACHE BOOL "Turn off building media plugins if they are imported by third-party library mechanism")
+set(ENABLE_MEDIA_PLUGINS ON CACHE BOOL "Turn off building media plugins if they are imported by third-party library mechanism")
if(LIBS_CLOSED_DIR)
file(TO_CMAKE_PATH "${LIBS_CLOSED_DIR}" LIBS_CLOSED_DIR)
diff --git a/indra/cmake/WebKitLibPlugin.cmake b/indra/cmake/WebKitLibPlugin.cmake
deleted file mode 100755
index f7c548a2fd..0000000000
--- a/indra/cmake/WebKitLibPlugin.cmake
+++ /dev/null
@@ -1,93 +0,0 @@
-# -*- cmake -*-
-include(Linking)
-include(Prebuilt)
-include(OpenSSL)
-
-if (USESYSTEMLIBS)
- # The minimal version, 4.4.3, is rather arbitrary: it's the version in Debian/Lenny.
- find_package(Qt4 4.4.3 COMPONENTS QtCore QtGui QtNetwork QtOpenGL QtWebKit REQUIRED)
- include(${QT_USE_FILE})
- set(QTDIR $ENV{QTDIR})
- if (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin")
- message(FATAL_ERROR "\"${QT_BINARY_DIR}\" is unequal \"${QTDIR}/bin\"; "
- "Qt is found by looking for qmake in your PATH. "
- "Please set your PATH such that 'qmake' is found in \$QTDIR/bin, "
- "or unset QTDIR if the found Qt is correct.")
- endif (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin")
- find_package(LLQtWebkit REQUIRED QUIET)
- # Add the plugins.
- set(QT_PLUGIN_LIBRARIES)
- foreach(qlibname qgif qjpeg)
- find_library(QT_PLUGIN_${qlibname} ${qlibname} PATHS ${QT_PLUGINS_DIR}/imageformats NO_DEFAULT_PATH)
- if (QT_PLUGIN_${qlibname})
- list(APPEND QT_PLUGIN_LIBRARIES ${QT_PLUGIN_${qlibname}})
- else (QT_PLUGIN_${qtlibname})
- message(FATAL_ERROR "Could not find the Qt plugin ${qlibname} in \"${QT_PLUGINS_DIR}/imageformats\"!")
- endif (QT_PLUGIN_${qlibname})
- endforeach(qlibname)
- # qjpeg depends on libjpeg
- list(APPEND QT_PLUGIN_LIBRARIES jpeg)
- set(WEBKITLIBPLUGIN OFF CACHE BOOL
- "WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.")
-else (USESYSTEMLIBS)
- use_prebuilt_binary(llqtwebkit)
- set(WEBKITLIBPLUGIN ON CACHE BOOL
- "WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.")
-endif (USESYSTEMLIBS)
-
-if (WINDOWS)
- set(WEBKIT_PLUGIN_LIBRARIES
- debug llqtwebkitd
- debug QtWebKitd4
- debug QtOpenGLd4
- debug QtNetworkd4
- debug QtGuid4
- debug QtCored4
- debug qtmaind
- optimized llqtwebkit
- optimized QtWebKit4
- optimized QtOpenGL4
- optimized QtNetwork4
- optimized QtGui4
- optimized QtCore4
- optimized qtmain
- )
-elseif (DARWIN)
- set(WEBKIT_PLUGIN_LIBRARIES
- ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.a
- ${ARCH_PREBUILT_DIRS_RELEASE}/libQtWebKit.4.dylib
- ${ARCH_PREBUILT_DIRS_RELEASE}/libQtOpenGL.4.dylib
- ${ARCH_PREBUILT_DIRS_RELEASE}/libQtNetwork.4.dylib
- ${ARCH_PREBUILT_DIRS_RELEASE}/libQtGui.4.dylib
- ${ARCH_PREBUILT_DIRS_RELEASE}/libQtCore.4.dylib
- )
-elseif (LINUX)
- # *HUH: What does this do?
- set(WEBKIT_PLUGIN_LIBRARIES ${LLQTWEBKIT_LIBRARY} ${QT_LIBRARIES} ${QT_PLUGIN_LIBRARIES})
- set(WEBKIT_PLUGIN_LIBRARIES
- llqtwebkit
-# qico
-# qpng
-# qtiff
-# qsvg
-# QtSvg
- QtWebKit
- QtOpenGL
- QtNetwork
- ${OPENSSL_LIBRARIES}
- QtGui
- QtCore
-# jscore
-# qgif
-# qjpeg
-# jpeg
- fontconfig
- X11
- Xrender
- GL
-
-# sqlite3
-# Xi
-# SM
- )
-endif (WINDOWS)
diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py
index 1d85aa2978..62bd09471a 100755
--- a/indra/lib/python/indra/util/llmanifest.py
+++ b/indra/lib/python/indra/util/llmanifest.py
@@ -512,11 +512,7 @@ class LLManifest(object):
# ensure that destination path exists
self.cmakedirs(os.path.dirname(dst))
self.created_paths.append(dst)
- if not os.path.isdir(src):
- self.ccopy(src,dst)
- else:
- # src is a dir
- self.ccopytree(src,dst)
+ self.ccopymumble(src, dst)
else:
print "Doesn't exist:", src
@@ -595,28 +591,38 @@ class LLManifest(object):
else:
os.remove(path)
- def ccopy(self, src, dst):
- """ Copy a single file or symlink. Uses filecmp to skip copying for existing files."""
+ def ccopymumble(self, src, dst):
+ """Copy a single symlink, file or directory."""
if os.path.islink(src):
linkto = os.readlink(src)
- if os.path.islink(dst) or os.path.exists(dst):
+ if os.path.islink(dst) or os.path.isfile(dst):
os.remove(dst) # because symlinking over an existing link fails
+ elif os.path.isdir(dst):
+ shutil.rmtree(dst)
os.symlink(linkto, dst)
+ elif os.path.isdir(src):
+ self.ccopytree(src, dst)
else:
- # Don't recopy file if it's up-to-date.
- # If we seem to be not not overwriting files that have been
- # updated, set the last arg to False, but it will take longer.
- if os.path.exists(dst) and filecmp.cmp(src, dst, True):
- return
- # only copy if it's not excluded
- if self.includes(src, dst):
- try:
- os.unlink(dst)
- except OSError, err:
- if err.errno != errno.ENOENT:
- raise
-
- shutil.copy2(src, dst)
+ self.ccopyfile(src, dst)
+ # XXX What about devices, sockets etc.?
+ # YYY would we put such things into a viewer package?!
+
+ def ccopyfile(self, src, dst):
+ """ Copy a single file. Uses filecmp to skip copying for existing files."""
+ # Don't recopy file if it's up-to-date.
+ # If we seem to be not not overwriting files that have been
+ # updated, set the last arg to False, but it will take longer.
+ if os.path.exists(dst) and filecmp.cmp(src, dst, True):
+ return
+ # only copy if it's not excluded
+ if self.includes(src, dst):
+ try:
+ os.unlink(dst)
+ except OSError, err:
+ if err.errno != errno.ENOENT:
+ raise
+
+ shutil.copy2(src, dst)
def ccopytree(self, src, dst):
"""Direct copy of shutil.copytree with the additional
@@ -632,11 +638,7 @@ class LLManifest(object):
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
try:
- if os.path.isdir(srcname):
- self.ccopytree(srcname, dstname)
- else:
- self.ccopy(srcname, dstname)
- # XXX What about devices, sockets etc.?
+ self.ccopymumble(srcname, dstname)
except (IOError, os.error), why:
errors.append((srcname, dstname, why))
if errors:
diff --git a/indra/llplugin/CMakeLists.txt b/indra/llplugin/CMakeLists.txt
index 05fc12e338..8c4ddd524e 100755
--- a/indra/llplugin/CMakeLists.txt
+++ b/indra/llplugin/CMakeLists.txt
@@ -20,7 +20,6 @@ include_directories(
${LLRENDER_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS}
- ${LLQTWEBKIT_INCLUDE_DIR}
)
include_directories(SYSTEM
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
@@ -68,7 +67,7 @@ list(APPEND llplugin_SOURCE_FILES ${llplugin_HEADER_FILES})
add_library (llplugin ${llplugin_SOURCE_FILES})
-##add_subdirectory(slplugin)
+add_subdirectory(slplugin)
# Add tests
if (LL_TESTS)
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 4bfd0de81e..3d173d0459 100755
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llpluginclassmedia.cpp
* @brief LLPluginClassMedia handles a plugin which knows about the "media" message class.
*
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
@@ -41,14 +41,13 @@ static int nextPowerOf2( int value )
{
next_power_of_2 <<= 1;
}
-
+
return next_power_of_2;
}
LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner)
{
mOwner = owner;
- mPlugin = NULL;
reset();
//debug use
@@ -63,19 +62,19 @@ LLPluginClassMedia::~LLPluginClassMedia()
}
bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
-{
+{
LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL;
LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL;
LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL;
-
- mPlugin = new LLPluginProcessParent(this);
+
+ mPlugin = LLPluginProcessParent::create(this);
mPlugin->setSleepTime(mSleepTime);
-
+
// Queue up the media init message -- it will be sent after all the currently queued messages.
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
message.setValue("target", mTarget);
sendMessage(message);
-
+
mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
return true;
@@ -84,10 +83,10 @@ bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::s
void LLPluginClassMedia::reset()
{
- if(mPlugin != NULL)
+ if(mPlugin)
{
- delete mPlugin;
- mPlugin = NULL;
+ mPlugin->requestShutdown();
+ mPlugin.reset();
}
mTextureParamsReceived = false;
@@ -115,7 +114,7 @@ void LLPluginClassMedia::reset()
mTextureHeight = 0;
mMediaWidth = 0;
mMediaHeight = 0;
- mDirtyRect = LLRect::null;
+ mDirtyRect = LLRect::null;
mAutoScaleMedia = false;
mRequestedVolume = 1.0f;
mPriority = PRIORITY_NORMAL;
@@ -132,7 +131,7 @@ void LLPluginClassMedia::reset()
mMediaName.clear();
mMediaDescription.clear();
mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f);
-
+
// media_browser class
mNavigateURI.clear();
mNavigateResultCode = -1;
@@ -140,7 +139,7 @@ void LLPluginClassMedia::reset()
mHistoryBackAvailable = false;
mHistoryForwardAvailable = false;
mStatusText.clear();
- mProgressPercent = 0;
+ mProgressPercent = 0;
mClickURL.clear();
mClickNavType.clear();
mClickTarget.clear();
@@ -148,7 +147,7 @@ void LLPluginClassMedia::reset()
mStatusCode = 0;
mClickEnforceTarget = false;
-
+
// media_time class
mCurrentTime = 0.0f;
mDuration = 0.0f;
@@ -162,7 +161,7 @@ void LLPluginClassMedia::idle(void)
{
mPlugin->idle();
}
-
+
if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
{
// Can't process a size change at this time
@@ -179,7 +178,7 @@ void LLPluginClassMedia::idle(void)
else
{
mRequestedTextureWidth = mRequestedMediaWidth;
-
+
if(mPadding > 1)
{
// Pad up to a multiple of the specified number of bytes per row
@@ -189,7 +188,7 @@ void LLPluginClassMedia::idle(void)
{
rowbytes += mPadding - pad;
}
-
+
if(rowbytes % mRequestedTextureDepth == 0)
{
mRequestedTextureWidth = rowbytes / mRequestedTextureDepth;
@@ -201,7 +200,7 @@ void LLPluginClassMedia::idle(void)
}
}
-
+
// Size change has been requested but not initiated yet.
size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth;
@@ -216,22 +215,22 @@ void LLPluginClassMedia::idle(void)
mPlugin->removeSharedMemory(mTextureSharedMemoryName);
mTextureSharedMemoryName.clear();
}
-
+
mTextureSharedMemorySize = newsize;
mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize);
if(!mTextureSharedMemoryName.empty())
{
void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
-
+
// clear texture memory to avoid random screen visual fuzz from uninitialized texture data
memset( addr, 0x00, newsize );
-
+
// We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin,
// so it may not be worthwhile.
// mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight);
}
}
-
+
// This is our local indicator that a change is in progress.
mTextureWidth = -1;
mTextureHeight = -1;
@@ -240,7 +239,7 @@ void LLPluginClassMedia::idle(void)
// This invalidates any existing dirty rect.
resetDirty();
-
+
// Send a size change message to the plugin
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change");
@@ -254,11 +253,11 @@ void LLPluginClassMedia::idle(void)
message.setValueReal("background_b", mBackgroundColor.mV[VZ]);
message.setValueReal("background_a", mBackgroundColor.mV[VW]);
mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue.
-
+
LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL;
}
}
-
+
if(mPlugin && mPlugin->isRunning())
{
// Send queued messages
@@ -324,11 +323,11 @@ void LLPluginClassMedia::setSizeInternal(void)
mRequestedMediaWidth = mDefaultMediaWidth;
mRequestedMediaHeight = mDefaultMediaHeight;
}
-
+
// Save these for size/interest calculations
mFullMediaWidth = mRequestedMediaWidth;
mFullMediaHeight = mRequestedMediaHeight;
-
+
if(mAllowDownsample)
{
switch(mPriority)
@@ -342,19 +341,19 @@ void LLPluginClassMedia::setSizeInternal(void)
mRequestedMediaHeight /= 2;
}
break;
-
+
default:
// Don't adjust texture size
break;
}
}
-
+
if(mAutoScaleMedia)
{
mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth);
mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight);
}
-
+
if(mRequestedMediaWidth > 2048)
mRequestedMediaWidth = 2048;
@@ -382,9 +381,9 @@ bool LLPluginClassMedia::textureValid(void)
mRequestedMediaWidth != mMediaWidth ||
mRequestedMediaHeight != mMediaHeight ||
getBitsData() == NULL
- )
+ )
return false;
-
+
return true;
}
@@ -408,8 +407,8 @@ void LLPluginClassMedia::resetDirty(void)
std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
{
std::string result;
-
-
+
+
if(modifiers & MASK_CONTROL)
{
result += "control|";
@@ -432,7 +431,7 @@ std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
{
result += "meta|";
}
-*/
+*/
return result;
}
@@ -540,11 +539,11 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int
// Don't spam unnecessary mouse move events.
return;
}
-
+
mLastMouseX = x;
mLastMouseY = y;
}
-
+
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
std::string temp;
switch(type)
@@ -559,7 +558,7 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int
message.setValueS32("button", button);
message.setValueS32("x", x);
-
+
// Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it.
if(!mRequestedTextureCoordsOpenGL)
{
@@ -569,42 +568,42 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int
message.setValueS32("y", y);
message.setValue("modifiers", translateModifiers(modifiers));
-
+
sendMessage(message);
}
bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data)
{
bool result = true;
-
+
// FIXME:
// HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode.
// For now, return false for the ones the webkit plugin won't handle properly.
-
+
switch(key_code)
{
- case KEY_BACKSPACE:
- case KEY_TAB:
- case KEY_RETURN:
- case KEY_PAD_RETURN:
- case KEY_SHIFT:
- case KEY_CONTROL:
- case KEY_ALT:
- case KEY_CAPSLOCK:
- case KEY_ESCAPE:
- case KEY_PAGE_UP:
- case KEY_PAGE_DOWN:
- case KEY_END:
- case KEY_HOME:
- case KEY_LEFT:
- case KEY_UP:
- case KEY_RIGHT:
- case KEY_DOWN:
- case KEY_INSERT:
+ case KEY_BACKSPACE:
+ case KEY_TAB:
+ case KEY_RETURN:
+ case KEY_PAD_RETURN:
+ case KEY_SHIFT:
+ case KEY_CONTROL:
+ case KEY_ALT:
+ case KEY_CAPSLOCK:
+ case KEY_ESCAPE:
+ case KEY_PAGE_UP:
+ case KEY_PAGE_DOWN:
+ case KEY_END:
+ case KEY_HOME:
+ case KEY_LEFT:
+ case KEY_UP:
+ case KEY_RIGHT:
+ case KEY_DOWN:
+ case KEY_INSERT:
case KEY_DELETE:
- // These will be handled
+ // These will be handled
break;
-
+
default:
// regular ASCII characters will also be handled
if(key_code >= KEY_SPECIAL)
@@ -615,7 +614,7 @@ bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifie
break;
}
-#if LL_DARWIN
+#if LL_DARWIN
if(modifiers & MASK_ALT)
{
// Option-key modified characters should be handled by the unicode input path instead of this one.
@@ -634,15 +633,15 @@ bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifie
case KEY_EVENT_REPEAT: temp = "repeat"; break;
}
message.setValue("event", temp);
-
+
message.setValueS32("key", key_code);
message.setValue("modifiers", translateModifiers(modifiers));
message.setValueLLSD("native_key_data", native_key_data);
-
+
sendMessage(message);
}
-
+
return result;
}
@@ -653,10 +652,10 @@ void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
message.setValueS32("x", x);
message.setValueS32("y", y);
message.setValue("modifiers", translateModifiers(modifiers));
-
+
sendMessage(message);
}
-
+
bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
@@ -664,18 +663,33 @@ bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD
message.setValue("text", text);
message.setValue("modifiers", translateModifiers(modifiers));
message.setValueLLSD("native_key_data", native_key_data);
-
+
sendMessage(message);
-
+
return true;
}
+void LLPluginClassMedia::setCookie(std::string uri, std::string name, std::string value, std::string domain, std::string path, bool httponly, bool secure)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_cookie");
+
+ message.setValue("uri", uri);
+ message.setValue("name", name);
+ message.setValue("value", value);
+ message.setValue("domain", domain);
+ message.setValue("path", path);
+ message.setValueBoolean("httponly", httponly);
+ message.setValueBoolean("secure", secure);
+
+ sendMessage(message);
+}
+
void LLPluginClassMedia::loadURI(const std::string &uri)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri");
message.setValue("uri", uri);
-
+
sendMessage(message);
}
@@ -692,7 +706,7 @@ const char* LLPluginClassMedia::priorityToString(EPriority priority)
case PRIORITY_NORMAL: result = "normal"; break;
case PRIORITY_HIGH: result = "high"; break;
}
-
+
return result;
}
@@ -703,44 +717,44 @@ void LLPluginClassMedia::setPriority(EPriority priority)
mPriority = priority;
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
-
+
std::string priority_string = priorityToString(priority);
switch(priority)
{
- case PRIORITY_UNLOADED:
+ case PRIORITY_UNLOADED:
mSleepTime = 1.0f;
break;
- case PRIORITY_STOPPED:
+ case PRIORITY_STOPPED:
mSleepTime = 1.0f;
break;
- case PRIORITY_HIDDEN:
+ case PRIORITY_HIDDEN:
mSleepTime = 1.0f;
break;
case PRIORITY_SLIDESHOW:
mSleepTime = 1.0f;
break;
- case PRIORITY_LOW:
+ case PRIORITY_LOW:
mSleepTime = 1.0f / 25.0f;
break;
- case PRIORITY_NORMAL:
+ case PRIORITY_NORMAL:
mSleepTime = 1.0f / 50.0f;
break;
- case PRIORITY_HIGH:
+ case PRIORITY_HIGH:
mSleepTime = 1.0f / 100.0f;
break;
}
-
+
message.setValue("priority", priority_string);
sendMessage(message);
-
+
if(mPlugin)
{
mPlugin->setSleepTime(mSleepTime);
}
-
+
LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL;
-
+
// This may affect the calculated size, so recalculate it here.
setSizeInternal();
}
@@ -761,12 +775,12 @@ void LLPluginClassMedia::setLowPrioritySizeLimit(int size)
F64 LLPluginClassMedia::getCPUUsage()
{
F64 result = 0.0f;
-
+
if(mPlugin)
{
result = mPlugin->getCPUUsage();
}
-
+
return result;
}
@@ -814,10 +828,11 @@ void LLPluginClassMedia::paste()
sendMessage(message);
}
-void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path)
+void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path_cache, const std::string &user_data_path_cookies)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path");
- message.setValue("path", user_data_path);
+ message.setValue("cache_path", user_data_path_cache);
+ message.setValue("cookies_path", user_data_path_cookies);
sendMessage(message);
}
@@ -830,14 +845,14 @@ void LLPluginClassMedia::setLanguageCode(const std::string &language_code)
void LLPluginClassMedia::setPluginsEnabled(const bool enabled)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "plugins_enabled");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "plugins_enabled");
message.setValueBoolean("enable", enabled);
sendMessage(message);
}
void LLPluginClassMedia::setJavascriptEnabled(const bool enabled)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "javascript_enabled");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "javascript_enabled");
message.setValueBoolean("enable", enabled);
sendMessage(message);
}
@@ -855,11 +870,11 @@ void LLPluginClassMedia::setTarget(const std::string &target)
mTarget = target;
}
-/* virtual */
+/* virtual */
void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
{
std::string message_class = message.getClass();
-
+
if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
{
std::string message_name = message.getName();
@@ -870,21 +885,21 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
mRequestedTextureFormat = message.getValueU32("format");
mRequestedTextureType = message.getValueU32("type");
mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes");
- mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");
-
+ mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");
+
// These two are optional, and will default to 0 if they're not specified.
mDefaultMediaWidth = message.getValueS32("default_width");
mDefaultMediaHeight = message.getValueS32("default_height");
-
+
mAllowDownsample = message.getValueBoolean("allow_downsample");
mPadding = message.getValueS32("padding");
setSizeInternal();
-
+
mTextureParamsReceived = true;
}
else if(message_name == "updated")
- {
+ {
if(message.hasValue("left"))
{
LLRect newDirtyRect;
@@ -892,7 +907,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
newDirtyRect.mTop = message.getValueS32("top");
newDirtyRect.mRight = message.getValueS32("right");
newDirtyRect.mBottom = message.getValueS32("bottom");
-
+
// The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion.
// If they're backwards, swap them.
if(newDirtyRect.mTop < newDirtyRect.mBottom)
@@ -901,7 +916,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
newDirtyRect.mTop = newDirtyRect.mBottom;
newDirtyRect.mBottom = temp;
}
-
+
if(mDirtyRect.isEmpty())
{
mDirtyRect = newDirtyRect;
@@ -911,7 +926,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
mDirtyRect.unionWith(newDirtyRect);
}
- LL_DEBUGS("Plugin") << "adjusted incoming rect is: ("
+ LL_DEBUGS("Plugin") << "adjusted incoming rect is: ("
<< newDirtyRect.mLeft << ", "
<< newDirtyRect.mTop << ", "
<< newDirtyRect.mRight << ", "
@@ -921,10 +936,10 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
<< mDirtyRect.mRight << ", "
<< mDirtyRect.mBottom << ")"
<< LL_ENDL;
-
+
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED);
- }
-
+ }
+
bool time_duration_updated = false;
int previous_percent = mProgressPercent;
@@ -944,7 +959,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
{
mCurrentRate = message.getValueReal("current_rate");
}
-
+
if(message.hasValue("loaded_duration"))
{
mLoadedDuration = message.getValueReal("loaded_duration");
@@ -955,7 +970,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
// If the message doesn't contain a loaded_duration param, assume it's equal to duration
mLoadedDuration = mDuration;
}
-
+
// Calculate a percentage based on the loaded duration and total duration.
if(mDuration != 0.0f) // Don't divide by zero.
{
@@ -966,7 +981,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
{
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
}
-
+
if(previous_percent != mProgressPercent)
{
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
@@ -975,9 +990,9 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
else if(message_name == "media_status")
{
std::string status = message.getValue("status");
-
+
LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL;
-
+
if(status == "loading")
{
mStatus = LLPluginClassMediaOwner::MEDIA_LOADING;
@@ -1017,24 +1032,24 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
// TODO: check that name matches?
mNaturalMediaWidth = width;
mNaturalMediaHeight = height;
-
+
setSizeInternal();
}
else if(message_name == "size_change_response")
{
std::string name = message.getValue("name");
-
+
// TODO: check that name matches?
-
+
mTextureWidth = message.getValueS32("texture_width");
mTextureHeight = message.getValueS32("texture_height");
mMediaWidth = message.getValueS32("width");
mMediaHeight = message.getValueS32("height");
-
+
// This invalidates any existing dirty rect.
resetDirty();
-
- // TODO: should we verify that the plugin sent back the right values?
+
+ // TODO: should we verify that the plugin sent back the right values?
// Two size changes in a row may cause them to not match, due to queueing, etc.
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED);
@@ -1075,6 +1090,11 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
mAuthRealm = message.getValue("realm");
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST);
}
+ else if (message_name == "file_download")
+ {
+ mFileDownloadFilename = message.getValue("filename");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_FILE_DOWNLOAD);
+ }
else if(message_name == "debug_message")
{
mDebugMessageText = message.getValue("message_text");
@@ -1101,7 +1121,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
mNavigateResultString = message.getValue("result_string");
mHistoryBackAvailable = message.getValueBoolean("history_back_available");
mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
-
+
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE);
}
else if(message_name == "progress")
@@ -1156,7 +1176,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
mGeometryY = message.getValueS32("y");
mGeometryWidth = message.getValueS32("width");
mGeometryHeight = message.getValueS32("height");
-
+
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE);
}
else if(message_name == "link_hovered")
@@ -1165,7 +1185,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
mHoverLink = message.getValue("link");
mHoverText = message.getValue("title");
// message.getValue("text");
-
+
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED);
}
else
@@ -1181,7 +1201,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
// if(message_name == "message_name")
// {
// }
-// else
+// else
{
LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
}
@@ -1189,13 +1209,13 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
}
-/* virtual */
+/* virtual */
void LLPluginClassMedia::pluginLaunchFailed()
{
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
}
-/* virtual */
+/* virtual */
void LLPluginClassMedia::pluginDied()
{
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
@@ -1235,7 +1255,7 @@ void LLPluginClassMedia::focus(bool focused)
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus");
message.setValueBoolean("focused", focused);
-
+
sendMessage(message);
}
@@ -1262,7 +1282,7 @@ void LLPluginClassMedia::clear_cookies()
void LLPluginClassMedia::set_cookies(const std::string &cookies)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies");
- message.setValue("cookies", cookies);
+ message.setValue("cookies", cookies);
sendMessage(message);
}
@@ -1295,7 +1315,7 @@ void LLPluginClassMedia::browse_reload(bool ignore_cache)
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload");
message.setValueBoolean("ignore_cache", ignore_cache);
-
+
sendMessage(message);
}
@@ -1415,7 +1435,7 @@ void LLPluginClassMedia::seek(float time)
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek");
message.setValueReal("time", time);
-
+
sendMessage(message);
}
@@ -1433,11 +1453,11 @@ void LLPluginClassMedia::setVolume(float volume)
if(volume != mRequestedVolume)
{
mRequestedVolume = volume;
-
+
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume");
message.setValueReal("volume", volume);
-
+
sendMessage(message);
}
}
@@ -1456,4 +1476,3 @@ void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL;
}
-
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index 96d577f43c..fc27b7bea3 100755
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -133,6 +133,8 @@ public:
// Text may be unicode (utf8 encoded)
bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
+ void setCookie(std::string uri, std::string name, std::string value, std::string domain, std::string path, bool httponly, bool secure);
+
void loadURI(const std::string &uri);
// "Loading" means uninitialized or any state prior to fully running (processing commands)
@@ -191,7 +193,7 @@ public:
bool canPaste() const { return mCanPaste; };
// These can be called before init(), and they will be queued and sent before the media init message.
- void setUserDataPath(const std::string &user_data_path);
+ void setUserDataPath(const std::string &user_data_path_cache, const std::string &user_data_path_cookies);
void setLanguageCode(const std::string &language_code);
void setPluginsEnabled(const bool enabled);
void setJavascriptEnabled(const bool enabled);
@@ -277,6 +279,10 @@ public:
std::string getHoverText() const { return mHoverText; };
std::string getHoverLink() const { return mHoverLink; };
+ // these are valid during MEDIA_EVENT_LINK_HOVERED
+ std::string getFileDownloadFilename() const { return mFileDownloadFilename; }
+
+
const std::string& getMediaName() const { return mMediaName; };
std::string getMediaDescription() const { return mMediaDescription; };
@@ -372,7 +378,7 @@ protected:
int mPadding;
- LLPluginProcessParent *mPlugin;
+ LLPluginProcessParent::ptr_t mPlugin;
LLRect mDirtyRect;
@@ -424,6 +430,7 @@ protected:
std::string mAuthRealm;
std::string mHoverText;
std::string mHoverLink;
+ std::string mFileDownloadFilename;
/////////////////////////////////////////
// media_time class
diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h
index 2f3edba7f3..391c23d883 100755
--- a/indra/llplugin/llpluginclassmediaowner.h
+++ b/indra/llplugin/llpluginclassmediaowner.h
@@ -64,6 +64,8 @@ public:
MEDIA_EVENT_AUTH_REQUEST, // The plugin wants to display an auth dialog
+ MEDIA_EVENT_FILE_DOWNLOAD, // the plugin wants to download a file
+
MEDIA_EVENT_DEBUG_MESSAGE, // plugin sending back debug information for host to process
MEDIA_EVENT_LINK_HOVERED // Got a "link hovered" event from the plugin
diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp
index f8a282184e..be80d38305 100755
--- a/indra/llplugin/llpluginprocesschild.cpp
+++ b/indra/llplugin/llpluginprocesschild.cpp
@@ -33,6 +33,7 @@
#include "llpluginmessagepipe.h"
#include "llpluginmessageclasses.h"
+static const F32 GOODBYE_SECONDS = 20.0f;
static const F32 HEARTBEAT_SECONDS = 1.0f;
static const F32 PLUGIN_IDLE_SECONDS = 1.0f / 100.0f; // Each call to idle will give the plugin this much time.
@@ -194,33 +195,43 @@ void LLPluginProcessChild::idle(void)
}
}
// receivePluginMessage will transition to STATE_UNLOADING
- break;
+ break;
+
+ case STATE_SHUTDOWNREQ:
+ if (mInstance != NULL)
+ {
+ sendMessageToPlugin(LLPluginMessage("base", "cleanup"));
+ delete mInstance;
+ mInstance = NULL;
+ }
+ setState(STATE_UNLOADING);
+ mWaitGoodbye.setTimerExpirySec(GOODBYE_SECONDS);
+ break;
case STATE_UNLOADING:
- if(mInstance != NULL)
- {
- sendMessageToPlugin(LLPluginMessage("base", "cleanup"));
- delete mInstance;
- mInstance = NULL;
- }
- setState(STATE_UNLOADED);
- break;
+ // waiting for goodbye from plugin.
+ if (mWaitGoodbye.hasExpired())
+ {
+ LL_WARNS() << "Wait for goodbye expired. Advancing to UNLOADED" << LL_ENDL;
+ setState(STATE_UNLOADED);
+ }
+ break;
case STATE_UNLOADED:
killSockets();
setState(STATE_DONE);
- break;
+ break;
case STATE_ERROR:
// Close the socket to the launcher
killSockets();
// TODO: Where do we go from here? Just exit()?
setState(STATE_DONE);
- break;
+ break;
case STATE_DONE:
// just sit here.
- break;
+ break;
}
} while (idle_again);
@@ -350,6 +361,10 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message)
mPluginFile = parsed.getValue("file");
mPluginDir = parsed.getValue("dir");
}
+ else if (message_name == "shutdown_plugin")
+ {
+ setState(STATE_SHUTDOWNREQ);
+ }
else if(message_name == "shm_add")
{
std::string name = parsed.getValue("name");
@@ -495,6 +510,10 @@ void LLPluginProcessChild::receivePluginMessage(const std::string &message)
// Let the parent know it's loaded and initialized.
sendMessageToParent(new_message);
}
+ else if (message_name == "goodbye")
+ {
+ setState(STATE_UNLOADED);
+ }
else if(message_name == "shm_remove_response")
{
// Don't pass this message up to the parent
diff --git a/indra/llplugin/llpluginprocesschild.h b/indra/llplugin/llpluginprocesschild.h
index 531422e792..b916cc9528 100755
--- a/indra/llplugin/llpluginprocesschild.h
+++ b/indra/llplugin/llpluginprocesschild.h
@@ -80,6 +80,7 @@ private:
STATE_PLUGIN_LOADED, // plugin library has been loaded
STATE_PLUGIN_INITIALIZING, // plugin is processing init message
STATE_RUNNING, // steady state (processing messages)
+ STATE_SHUTDOWNREQ, // Parent has requested a shutdown.
STATE_UNLOADING, // plugin has sent shutdown_response and needs to be unloaded
STATE_UNLOADED, // plugin has been unloaded
STATE_ERROR, // generic bailout state
@@ -101,12 +102,12 @@ private:
sharedMemoryRegionsType mSharedMemoryRegions;
LLTimer mHeartbeat;
- F64 mSleepTime;
- F64 mCPUElapsed;
+ F64 mSleepTime;
+ F64 mCPUElapsed;
bool mBlockingRequest;
bool mBlockingResponseReceived;
std::queue<std::string> mMessageQueue;
-
+ LLTimer mWaitGoodbye;
void deliverQueuedMessages();
};
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index b5a2588e1e..0a8e58ac90 100755
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -46,7 +46,7 @@ bool LLPluginProcessParent::sUseReadThread = false;
apr_pollset_t *LLPluginProcessParent::sPollSet = NULL;
bool LLPluginProcessParent::sPollsetNeedsRebuild = false;
LLMutex *LLPluginProcessParent::sInstancesMutex;
-std::list<LLPluginProcessParent*> LLPluginProcessParent::sInstances;
+LLPluginProcessParent::mapInstances_t LLPluginProcessParent::sInstances;
LLThread *LLPluginProcessParent::sReadThread = NULL;
@@ -104,27 +104,12 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
// Don't start the timer here -- start it when we actually launch the plugin process.
mHeartbeat.stop();
- // Don't add to the global list until fully constructed.
- {
- LLMutexLock lock(sInstancesMutex);
- sInstances.push_back(this);
- }
}
LLPluginProcessParent::~LLPluginProcessParent()
{
LL_DEBUGS("Plugin") << "destructor" << LL_ENDL;
- // Remove from the global list before beginning destruction.
- {
- // Make sure to get the global mutex _first_ here, to avoid a possible deadlock against LLPluginProcessParent::poll()
- LLMutexLock lock(sInstancesMutex);
- {
- LLMutexLock lock2(&mIncomingQueueMutex);
- sInstances.remove(this);
- }
- }
-
// Destroy any remaining shared memory regions
sharedMemoryRegionsType::iterator iter;
while((iter = mSharedMemoryRegions.begin()) != mSharedMemoryRegions.end())
@@ -139,9 +124,109 @@ LLPluginProcessParent::~LLPluginProcessParent()
}
LLProcess::kill(mProcess);
- killSockets();
+ if (!LLApp::isQuitting())
+ { // If we are quitting, the network sockets will already have been destroyed.
+ killSockets();
+ }
+}
+
+/*static*/
+LLPluginProcessParent::ptr_t LLPluginProcessParent::create(LLPluginProcessParentOwner *owner)
+{
+ ptr_t that(new LLPluginProcessParent(owner));
+
+ // Don't add to the global list until fully constructed.
+ {
+ LLMutexLock lock(sInstancesMutex);
+ sInstances.insert(mapInstances_t::value_type(that.get(), that));
+ }
+
+ return that;
+}
+
+/*static*/
+void LLPluginProcessParent::shutdown()
+{
+ LLMutexLock lock(sInstancesMutex);
+
+ mapInstances_t::iterator it;
+ for (it = sInstances.begin(); it != sInstances.end(); ++it)
+ {
+ (*it).second->setState(STATE_GOODBYE);
+ (*it).second->idle();
+ }
+ sInstances.clear();
+}
+
+
+void LLPluginProcessParent::requestShutdown()
+{
+ setState(STATE_GOODBYE);
+ mOwner = NULL;
+
+ if (LLApp::isQuitting())
+ { // if we're quitting, run the idle once more
+ idle();
+ removeFromProcessing();
+ return;
+ }
+
+ static uint32_t count = 0;
+ std::stringstream namestream;
+
+ namestream << "LLPluginProcessParentListener" << ++count;
+
+ //*HACK!*//
+ // After requestShutdown has been called our previous owner will no longer call
+ // our idle() method. Tie into the event loop here to do that until we are good
+ // and finished.
+ LL_DEBUGS("LLPluginProcessParent") << "listening on \"mainloop\"" << LL_ENDL;
+ mPolling = LLEventPumps::instance().obtain("mainloop")
+ .listen(namestream.str(), boost::bind(&LLPluginProcessParent::pollTick, this));
+
+}
+
+bool LLPluginProcessParent::pollTick()
+{
+ if (isDone())
+ {
+ ptr_t that;
+ {
+ // this grabs a copy of the smart pointer to ourselves to ensure that we do not
+ // get destroyed until after this method returns.
+ LLMutexLock lock(sInstancesMutex);
+ mapInstances_t::iterator it = sInstances.find(this);
+ if (it != sInstances.end())
+ that = (*it).second;
+ }
+
+ removeFromProcessing();
+ return true;
+ }
+
+ idle();
+ return false;
}
+void LLPluginProcessParent::removeFromProcessing()
+{
+ // Remove from the global list before beginning destruction.
+ {
+ // Make sure to get the global mutex _first_ here, to avoid a possible deadlock against LLPluginProcessParent::poll()
+ LLMutexLock lock(sInstancesMutex);
+ {
+ LLMutexLock lock2(&mIncomingQueueMutex);
+ sInstances.erase(this);
+ }
+ }
+}
+
+bool LLPluginProcessParent::wantsPolling() const
+{
+ return (mPollFD.client_data && (mState != STATE_DONE));
+}
+
+
void LLPluginProcessParent::killSockets(void)
{
{
@@ -371,48 +456,48 @@ void LLPluginProcessParent::idle(void)
break;
case STATE_LISTENING:
- {
- // Launch the plugin process.
+ {
+ // Launch the plugin process.
- // 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(mDebug)
- {
- #if LL_DARWIN
- // If we're set to debug, start up a gdb instance in a new terminal window and have it attach to the plugin process and continue.
+ // 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(mDebug)
+ {
+#if LL_DARWIN
+ // If we're set to debug, start up a gdb instance in a new terminal window and have it attach to the plugin process and continue.
- // The command we're constructing would look like this on the command line:
- // osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell'
-
- LLProcess::Params params;
- params.executable = "/usr/bin/osascript";
- params.args.add("-e");
- params.args.add("tell application \"Terminal\"");
- params.args.add("-e");
- params.args.add(STRINGIZE("set win to do script \"gdb -pid "
- << mProcess->getProcessID() << "\""));
- params.args.add("-e");
- params.args.add("do script \"continue\" in win");
- params.args.add("-e");
- params.args.add("end tell");
- mDebugger = LLProcess::create(params);
-
- #endif
- }
+ // The command we're constructing would look like this on the command line:
+ // osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell'
+
+ LLProcess::Params params;
+ params.executable = "/usr/bin/osascript";
+ params.args.add("-e");
+ params.args.add("tell application \"Terminal\"");
+ params.args.add("-e");
+ params.args.add(STRINGIZE("set win to do script \"gdb -pid "
+ << mProcess->getProcessID() << "\""));
+ params.args.add("-e");
+ params.args.add("do script \"continue\" in win");
+ params.args.add("-e");
+ params.args.add("end tell");
+ mDebugger = LLProcess::create(params);
+
+#endif
+ }
- // This will allow us to time out if the process never starts.
- mHeartbeat.start();
- mHeartbeat.setTimerExpirySec(mPluginLaunchTimeout);
- setState(STATE_LAUNCHED);
- }
- }
- break;
+ // This will allow us to time out if the process never starts.
+ mHeartbeat.start();
+ mHeartbeat.setTimerExpirySec(mPluginLaunchTimeout);
+ setState(STATE_LAUNCHED);
+ }
+ }
+ break;
case STATE_LAUNCHED:
// waiting for the plugin to connect
@@ -430,7 +515,7 @@ void LLPluginProcessParent::idle(void)
setState(STATE_CONNECTED);
}
}
- break;
+ break;
case STATE_CONNECTED:
// waiting for hello message from the plugin
@@ -439,7 +524,7 @@ void LLPluginProcessParent::idle(void)
{
errorState();
}
- break;
+ break;
case STATE_HELLO:
LL_DEBUGS("Plugin") << "received hello message" << LL_ENDL;
@@ -453,7 +538,7 @@ void LLPluginProcessParent::idle(void)
}
setState(STATE_LOADING);
- break;
+ break;
case STATE_LOADING:
// The load_plugin_response message will kick us from here into STATE_RUNNING
@@ -461,15 +546,23 @@ void LLPluginProcessParent::idle(void)
{
errorState();
}
- break;
+ break;
case STATE_RUNNING:
if(pluginLockedUpOrQuit())
{
errorState();
}
- break;
+ break;
+ case STATE_GOODBYE:
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shutdown_plugin");
+ sendMessage(message);
+ }
+ setState(STATE_EXITING);
+ break;
+
case STATE_EXITING:
if (! LLProcess::isRunning(mProcess))
{
@@ -480,7 +573,7 @@ void LLPluginProcessParent::idle(void)
LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << LL_ENDL;
errorState();
}
- break;
+ break;
case STATE_LAUNCH_FAILURE:
if(mOwner != NULL)
@@ -488,7 +581,7 @@ void LLPluginProcessParent::idle(void)
mOwner->pluginLaunchFailed();
}
setState(STATE_CLEANUP);
- break;
+ break;
case STATE_ERROR:
if(mOwner != NULL)
@@ -496,19 +589,18 @@ void LLPluginProcessParent::idle(void)
mOwner->pluginDied();
}
setState(STATE_CLEANUP);
- break;
+ break;
case STATE_CLEANUP:
LLProcess::kill(mProcess);
killSockets();
setState(STATE_DONE);
- break;
-
+ dirtyPollSet();
+ break;
case STATE_DONE:
// just sit here.
- break;
-
+ break;
}
} while (idle_again);
@@ -651,14 +743,14 @@ void LLPluginProcessParent::updatePollset()
sPollSet = NULL;
}
- std::list<LLPluginProcessParent*>::iterator iter;
+ mapInstances_t::iterator iter;
int count = 0;
// Count the number of instances that want to be in the pollset
for(iter = sInstances.begin(); iter != sInstances.end(); iter++)
{
- (*iter)->mPolledInput = false;
- if((*iter)->mPollFD.client_data)
+ (*iter).second->mPolledInput = false;
+ if ((*iter).second->wantsPolling())
{
// This instance has a socket that needs to be polled.
++count;
@@ -686,12 +778,12 @@ void LLPluginProcessParent::updatePollset()
// Pollset was created, add all instances to it.
for(iter = sInstances.begin(); iter != sInstances.end(); iter++)
{
- if((*iter)->mPollFD.client_data)
+ if ((*iter).second->wantsPolling())
{
- status = apr_pollset_add(sPollSet, &((*iter)->mPollFD));
+ status = apr_pollset_add(sPollSet, &((*iter).second->mPollFD));
if(status == APR_SUCCESS)
{
- (*iter)->mPolledInput = true;
+ (*iter).second->mPolledInput = true;
}
else
{
@@ -756,45 +848,27 @@ void LLPluginProcessParent::poll(F64 timeout)
if(status == APR_SUCCESS)
{
// One or more of the descriptors signalled. Call them.
- for(int i = 0; i < count; i++)
- {
- LLPluginProcessParent *self = (LLPluginProcessParent *)(descriptors[i].client_data);
- // NOTE: the descriptor returned here is actually a COPY of the original (even though we create the pollset with APR_POLLSET_NOCOPY).
- // This means that even if the parent has set its mPollFD.client_data to NULL, the old pointer may still there in this descriptor.
- // It's even possible that the old pointer no longer points to a valid LLPluginProcessParent.
- // This means that we can't safely dereference the 'self' pointer here without some extra steps...
- if(self)
- {
- // Make sure this pointer is still in the instances list
- bool valid = false;
- {
- LLMutexLock lock(sInstancesMutex);
- for(std::list<LLPluginProcessParent*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter)
- {
- if(*iter == self)
- {
- // Lock the instance's mutex before unlocking the global mutex.
- // This avoids a possible race condition where the instance gets deleted between this check and the servicePoll() call.
- self->mIncomingQueueMutex.lock();
- valid = true;
- break;
- }
- }
- }
-
- if(valid)
- {
- // The instance is still valid.
- // Pull incoming messages off the socket
- self->servicePoll();
- self->mIncomingQueueMutex.unlock();
- }
- else
- {
- LL_DEBUGS("PluginPoll") << "detected deleted instance " << self << LL_ENDL;
- }
+ for (int i = 0; i < count; i++)
+ {
+ void *thatId = descriptors[i].client_data;
+
+ ptr_t that;
+ mapInstances_t::iterator it;
+
+ {
+ LLMutexLock lock(sInstancesMutex);
+ it = sInstances.find(thatId);
+ if (it != sInstances.end())
+ that = (*it).second;
+ }
+
+ if (that)
+ {
+ that->mIncomingQueueMutex.lock();
+ that->servicePoll();
+ that->mIncomingQueueMutex.unlock();
+ }
- }
}
}
else if(APR_STATUS_IS_TIMEUP(status))
@@ -812,6 +886,16 @@ void LLPluginProcessParent::poll(F64 timeout)
LL_WARNS("PluginPoll") << "apr_pollset_poll failed with status " << status << LL_ENDL;
}
}
+
+ // Remove instances in the done state from the sInstances map.
+ mapInstances_t::iterator itClean = sInstances.begin();
+ while (itClean != sInstances.end())
+ {
+ if ((*itClean).second->isDone())
+ sInstances.erase(itClean++);
+ else
+ ++itClean;
+ }
}
void LLPluginProcessParent::servicePoll()
diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h
index 24be7eb148..df1630255c 100755
--- a/indra/llplugin/llpluginprocessparent.h
+++ b/indra/llplugin/llpluginprocessparent.h
@@ -30,6 +30,7 @@
#define LL_LLPLUGINPROCESSPARENT_H
#include <queue>
+#include <boost/enable_shared_from_this.hpp>
#include "llapr.h"
#include "llprocess.h"
@@ -40,8 +41,9 @@
#include "lliosocket.h"
#include "llthread.h"
#include "llsd.h"
+#include "llevents.h"
-class LLPluginProcessParentOwner
+class LLPluginProcessParentOwner : public boost::enable_shared_from_this < LLPluginProcessParentOwner >
{
public:
virtual ~LLPluginProcessParentOwner();
@@ -55,8 +57,11 @@ public:
class LLPluginProcessParent : public LLPluginMessagePipeOwner
{
LOG_CLASS(LLPluginProcessParent);
+
+ LLPluginProcessParent(LLPluginProcessParentOwner *owner);
public:
- LLPluginProcessParent(LLPluginProcessParentOwner *owner);
+ typedef boost::shared_ptr<LLPluginProcessParent> ptr_t;
+
~LLPluginProcessParent();
void init(const std::string &launcher_filename,
@@ -89,7 +94,10 @@ public:
void sendMessage(const LLPluginMessage &message);
void receiveMessage(const LLPluginMessage &message);
-
+
+ static ptr_t create(LLPluginProcessParentOwner *owner);
+ void requestShutdown();
+
// Inherited from LLPluginMessagePipeOwner
/*virtual*/ void receiveMessageRaw(const std::string &message);
/*virtual*/ void receiveMessageEarly(const LLPluginMessage &message);
@@ -121,7 +129,10 @@ public:
static bool canPollThreadRun() { return (sPollSet || sPollsetNeedsRebuild || sUseReadThread); };
static void setUseReadThread(bool use_read_thread);
static bool getUseReadThread() { return sUseReadThread; };
+
+ static void shutdown();
private:
+ typedef std::map<void *, ptr_t> mapInstances_t;
enum EState
{
@@ -133,6 +144,7 @@ private:
STATE_HELLO, // first message from the plugin process has been received
STATE_LOADING, // process has been asked to load the plugin
STATE_RUNNING, //
+ STATE_GOODBYE,
STATE_LAUNCH_FAILURE, // Failure before plugin loaded
STATE_ERROR, // generic bailout state
STATE_CLEANUP, // clean everything up
@@ -143,6 +155,9 @@ private:
EState mState;
void setState(EState state);
+ bool wantsPolling() const;
+ void removeFromProcessing();
+
bool pluginLockedUp();
bool pluginLockedUpOrQuit();
@@ -185,12 +200,15 @@ private:
static apr_pollset_t *sPollSet;
static bool sPollsetNeedsRebuild;
static LLMutex *sInstancesMutex;
- static std::list<LLPluginProcessParent*> sInstances;
+ static mapInstances_t sInstances;
static void dirtyPollSet();
static void updatePollset();
void servicePoll();
static LLThread *sReadThread;
-
+
+ LLTempBoundListener mPolling;
+ bool pollTick();
+
LLMutex mIncomingQueueMutex;
std::queue<LLPluginMessage> mIncomingQueue;
};
diff --git a/indra/llplugin/slplugin/slplugin.cpp b/indra/llplugin/slplugin/slplugin.cpp
index 6c9ba0ae52..684bcf1207 100755
--- a/indra/llplugin/slplugin/slplugin.cpp
+++ b/indra/llplugin/slplugin/slplugin.cpp
@@ -310,4 +310,3 @@ int main(int argc, char **argv)
return 0;
}
-
diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp
index 547f0bd398..1a51b96fdf 100755
--- a/indra/llui/llfocusmgr.cpp
+++ b/indra/llui/llfocusmgr.cpp
@@ -47,11 +47,29 @@ BOOL LLFocusableElement::handleKey(KEY key, MASK mask, BOOL called_from_parent)
}
// virtual
+BOOL LLFocusableElement::handleKeyUp(KEY key, MASK mask, BOOL called_from_parent)
+{
+ return FALSE;
+}
+
+// virtual
BOOL LLFocusableElement::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
{
return FALSE;
}
+// virtual
+bool LLFocusableElement::wantsKeyUpKeyDown() const
+{
+ return false;
+}
+
+//virtual
+bool LLFocusableElement::wantsReturnKey() const
+{
+ return false;
+}
+
// virtual
LLFocusableElement::~LLFocusableElement()
{
diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h
index afd2a8ce06..0e3d7d8e59 100755
--- a/indra/llui/llfocusmgr.h
+++ b/indra/llui/llfocusmgr.h
@@ -57,8 +57,17 @@ public:
// These were brought up the hierarchy from LLView so that we don't have to use dynamic_cast when dealing with keyboard focus.
virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+ virtual BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent);
virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
+ /**
+ * If true this LLFocusableElement wants to receive KEYUP and KEYDOWN messages
+ * even for normal character strokes.
+ * Default implementation returns false.
+ */
+ virtual bool wantsKeyUpKeyDown() const;
+ virtual bool wantsReturnKey() const;
+
virtual void onTopLost(); // called when registered as top ctrl and user clicks elsewhere
protected:
virtual void onFocusReceived();
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index a8beb9cfc9..8f7cac1f61 100755
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -866,6 +866,7 @@ BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
return handled;
}
+
BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
{
BOOL handled = FALSE;
@@ -898,6 +899,38 @@ BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
return handled;
}
+BOOL LLView::handleKeyUp(KEY key, MASK mask, BOOL called_from_parent)
+{
+ BOOL handled = FALSE;
+
+ if (getVisible() && getEnabled())
+ {
+ if (called_from_parent)
+ {
+ // Downward traversal
+ handled = childrenHandleKeyUp(key, mask) != NULL;
+ }
+
+ if (!handled)
+ {
+ // For event logging we don't care which widget handles it
+ // So we capture the key at the end of this function once we know if it was handled
+ handled = handleKeyUpHere(key, mask);
+ if (handled)
+ {
+ LL_DEBUGS() << "Key handled by " << getName() << LL_ENDL;
+ }
+ }
+ }
+
+ if (!handled && !called_from_parent && mParentView)
+ {
+ // Upward traversal
+ handled = mParentView->handleKeyUp(key, mask, FALSE);
+ }
+ return handled;
+}
+
// Called from handleKey()
// Handles key in this object. Checking parents and children happens in handleKey()
BOOL LLView::handleKeyHere(KEY key, MASK mask)
@@ -905,6 +938,13 @@ BOOL LLView::handleKeyHere(KEY key, MASK mask)
return FALSE;
}
+// Called from handleKey()
+// Handles key in this object. Checking parents and children happens in handleKey()
+BOOL LLView::handleKeyUpHere(KEY key, MASK mask)
+{
+ return FALSE;
+}
+
BOOL LLView::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
{
BOOL handled = FALSE;
@@ -1021,6 +1061,12 @@ LLView* LLView::childrenHandleKey(KEY key, MASK mask)
}
// Called during downward traversal
+LLView* LLView::childrenHandleKeyUp(KEY key, MASK mask)
+{
+ return childrenHandleCharEvent("Key Up", &LLView::handleKeyUp, key, mask);
+}
+
+// Called during downward traversal
LLView* LLView::childrenHandleUnicodeChar(llwchar uni_char)
{
return childrenHandleCharEvent("Unicode character", &LLView::handleUnicodeCharWithDummyMask,
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 7861c8f729..8494bb338a 100755
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -378,6 +378,7 @@ public:
// inherited from LLFocusableElement
/* virtual */ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+ /* virtual */ BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent);
/* virtual */ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
@@ -509,6 +510,7 @@ public:
//virtual BOOL addChildFromParam(const LLInitParam::BaseBlock& params) { return TRUE; }
virtual BOOL handleKeyHere(KEY key, MASK mask);
+ virtual BOOL handleKeyUpHere(KEY key, MASK mask);
virtual BOOL handleUnicodeCharHere(llwchar uni_char);
virtual void handleReshape(const LLRect& rect, bool by_user);
@@ -538,6 +540,7 @@ protected:
void logMouseEvent();
LLView* childrenHandleKey(KEY key, MASK mask);
+ LLView* childrenHandleKeyUp(KEY key, MASK mask);
LLView* childrenHandleUnicodeChar(llwchar uni_char);
LLView* childrenHandleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop,
diff --git a/indra/llwindow/llkeyboardwin32.cpp b/indra/llwindow/llkeyboardwin32.cpp
index dc40dcdde0..2123ed3939 100755
--- a/indra/llwindow/llkeyboardwin32.cpp
+++ b/indra/llwindow/llkeyboardwin32.cpp
@@ -258,7 +258,7 @@ void LLKeyboardWin32::scanKeyboard()
// *TODO: I KNOW there must be a better way of
// interrogating the key state than this, using async key
// state can cause ALL kinds of bugs - Doug
- if (key < KEY_BUTTON0)
+ if ((key < KEY_BUTTON0) && ((key < '0') || (key > '9')))
{
// ...under windows make sure the key actually still is down.
// ...translate back to windows key
@@ -267,7 +267,7 @@ void LLKeyboardWin32::scanKeyboard()
if (!pending_key_events && !(GetAsyncKeyState(virtual_key) & 0x8000))
{
//LL_INFOS() << "Key up event missed, resetting" << LL_ENDL;
- mKeyLevel[key] = FALSE;
+ mKeyLevel[key] = FALSE;
}
}
}
diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm
index deb8cb90d8..406bc9cf47 100644
--- a/indra/llwindow/llopenglview-objc.mm
+++ b/indra/llwindow/llopenglview-objc.mm
@@ -28,6 +28,11 @@
#include "llwindowmacosx-objc.h"
#import "llappdelegate-objc.h"
+
+
+
+//---------------------------
+
@implementation NSScreen (PointConversion)
+ (NSScreen *)currentScreenForMouseLocation
@@ -42,6 +47,7 @@
return screen;
}
+
- (NSPoint)convertPointToScreenCoordinates:(NSPoint)aPoint
{
float normalizedX = fabs(fabs(self.frame.origin.x) - fabs(aPoint.x));
@@ -57,6 +63,21 @@
@end
+void extractKeyDataFromEvent (NSEvent *theEvent, NativeKeyEventData * eventData)
+{
+ eventData->mKeyEvent = NativeKeyEventData::KEYUNKNOWN;
+ eventData->mEventType = [theEvent type];
+ eventData->mEventModifiers = [theEvent modifierFlags];
+ eventData->mEventKeyCode = [theEvent keyCode];
+ NSString *strEventChars = [theEvent characters];
+ eventData->mEventChars = (strEventChars.length) ? [strEventChars characterAtIndex:0] : 0;
+ NSString *strEventUChars = [theEvent charactersIgnoringModifiers];
+ eventData->mEventUnmodChars = (strEventUChars.length) ? [strEventUChars characterAtIndex:0] : 0;
+ eventData->mEventRepeat = [theEvent isARepeat];
+
+}
+
+
attributedStringInfo getSegments(NSAttributedString *str)
{
attributedStringInfo segments;
@@ -402,11 +423,20 @@ attributedStringInfo getSegments(NSAttributedString *str)
- (void) keyUp:(NSEvent *)theEvent
{
- callKeyUp([theEvent keyCode], [theEvent modifierFlags]);
+ NativeKeyEventData eventData;
+
+ extractKeyDataFromEvent( theEvent, &eventData );
+ eventData.mKeyEvent = NativeKeyEventData::KEYUP;
+ callKeyUp(&eventData, [theEvent keyCode], [theEvent modifierFlags]);
}
- (void) keyDown:(NSEvent *)theEvent
{
+ NativeKeyEventData eventData;
+
+ extractKeyDataFromEvent( theEvent, &eventData );
+ eventData.mKeyEvent = NativeKeyEventData::KEYDOWN;
+
uint keycode = [theEvent keyCode];
// We must not depend on flagsChange event to detect modifier flags changed,
// must depend on the modifire flags in the event parameter.
@@ -414,7 +444,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
// e.g. OS Window for upload something or Input Window...
// mModifiers instance variable is for insertText: or insertText:replacementRange: (by Pell Smit)
mModifiers = [theEvent modifierFlags];
- bool acceptsText = mHasMarkedText ? false : callKeyDown(keycode, mModifiers);
+ bool acceptsText = mHasMarkedText ? false : callKeyDown(&eventData, keycode, mModifiers);
unichar ch;
if (acceptsText &&
!mMarkedTextAllowed &&
@@ -435,12 +465,17 @@ attributedStringInfo getSegments(NSAttributedString *str)
// Since SL assumes we receive those, we fake it here.
if (mModifiers & NSCommandKeyMask && !mHasMarkedText)
{
- callKeyUp([theEvent keyCode], mModifiers);
+ eventData.mKeyEvent = NativeKeyEventData::KEYUP;
+ callKeyUp(&eventData, [theEvent keyCode], mModifiers);
}
}
- (void)flagsChanged:(NSEvent *)theEvent
{
+ NativeKeyEventData eventData;
+
+ extractKeyDataFromEvent( theEvent, &eventData );
+
mModifiers = [theEvent modifierFlags];
callModifier([theEvent modifierFlags]);
@@ -462,11 +497,13 @@ attributedStringInfo getSegments(NSAttributedString *str)
if (mModifiers & mask)
{
- callKeyDown([theEvent keyCode], 0);
+ eventData.mKeyEvent = NativeKeyEventData::KEYDOWN;
+ callKeyDown(&eventData, [theEvent keyCode], 0);
}
else
{
- callKeyUp([theEvent keyCode], 0);
+ eventData.mKeyEvent = NativeKeyEventData::KEYUP;
+ callKeyUp(&eventData, [theEvent keyCode], 0);
}
}
diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h
index e6e8f27f53..dc184b91fb 100755
--- a/indra/llwindow/llwindowmacosx-objc.h
+++ b/indra/llwindow/llwindowmacosx-objc.h
@@ -46,6 +46,26 @@ typedef void *CursorRef;
typedef void *NSWindowRef;
typedef void *GLViewRef;
+
+struct NativeKeyEventData {
+ enum EventType {
+ KEYUNKNOWN,
+ KEYUP,
+ KEYDOWN,
+ KEYCHAR
+ };
+
+ EventType mKeyEvent;
+ uint32_t mEventType;
+ uint32_t mEventModifiers;
+ uint32_t mEventKeyCode;
+ uint32_t mEventChars;
+ uint32_t mEventUnmodChars;
+ bool mEventRepeat;
+};
+
+typedef const NativeKeyEventData * NSKeyEventRef;
+
// These are defined in llappviewermacosx.cpp.
bool initViewer();
void handleQuit();
@@ -102,8 +122,8 @@ void setupInputWindow(NSWindowRef window, GLViewRef view);
// These are all implemented in llwindowmacosx.cpp.
// This is largely for easier interop between Obj-C and C++ (at least in the viewer's case due to the BOOL vs. BOOL conflict)
-bool callKeyUp(unsigned short key, unsigned int mask);
-bool callKeyDown(unsigned short key, unsigned int mask);
+bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask);
+bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask);
void callResetKeys();
bool callUnicodeCallback(wchar_t character, unsigned int mask);
void callRightMouseDown(float *pos, unsigned int mask);
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index 15e054fb5d..0d41884462 100755
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -47,6 +47,10 @@ extern BOOL gDebugWindowProc;
const S32 BITS_PER_PIXEL = 32;
const S32 MAX_NUM_RESOLUTIONS = 32;
+namespace
+{
+ NSKeyEventRef mRawKeyEvent = NULL;
+}
//
// LLWindowMacOSX
//
@@ -194,14 +198,20 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
// These functions are used as wrappers for our internal event handling callbacks.
// It's a good idea to wrap these to avoid reworking more code than we need to within LLWindow.
-bool callKeyUp(unsigned short key, unsigned int mask)
+bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask)
{
- return gKeyboard->handleKeyUp(key, mask);
+ mRawKeyEvent = event;
+ bool retVal = gKeyboard->handleKeyUp(key, mask);
+ mRawKeyEvent = NULL;
+ return retVal;
}
-bool callKeyDown(unsigned short key, unsigned int mask)
+bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask)
{
- return gKeyboard->handleKeyDown(key, mask);
+ mRawKeyEvent = event;
+ bool retVal = gKeyboard->handleKeyDown(key, mask);
+ mRawKeyEvent = NULL;
+ return retVal;
}
void callResetKeys()
@@ -211,7 +221,23 @@ void callResetKeys()
bool callUnicodeCallback(wchar_t character, unsigned int mask)
{
- return gWindowImplementation->getCallbacks()->handleUnicodeChar(character, mask);
+ NativeKeyEventData eventData;
+
+ memset(&eventData, 0, sizeof(NativeKeyEventData));
+
+ eventData.mKeyEvent = NativeKeyEventData::KEYCHAR;
+ eventData.mEventType = 0;
+ eventData.mEventModifiers = mask;
+ eventData.mEventKeyCode = 0;
+ eventData.mEventChars = character;
+ eventData.mEventUnmodChars = character;
+ eventData.mEventRepeat = false;
+
+ mRawKeyEvent = &eventData;
+
+ bool result = gWindowImplementation->getCallbacks()->handleUnicodeChar(character, mask);
+ mRawKeyEvent = NULL;
+ return result;
}
void callFocus()
@@ -1713,49 +1739,15 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async)
LLSD LLWindowMacOSX::getNativeKeyData()
{
LLSD result = LLSD::emptyMap();
-#if 0
+#if 1
if(mRawKeyEvent)
{
- char char_code = 0;
- UInt32 key_code = 0;
- UInt32 modifiers = 0;
- UInt32 keyboard_type = 0;
-
- GetEventParameter (mRawKeyEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &char_code);
- GetEventParameter (mRawKeyEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &key_code);
- GetEventParameter (mRawKeyEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
- GetEventParameter (mRawKeyEvent, kEventParamKeyboardType, typeUInt32, NULL, sizeof(UInt32), NULL, &keyboard_type);
-
- result["char_code"] = (S32)char_code;
- result["key_code"] = (S32)key_code;
- result["modifiers"] = (S32)modifiers;
- result["keyboard_type"] = (S32)keyboard_type;
-
-#if 0
- // This causes trouble for control characters -- apparently character codes less than 32 (escape, control-A, etc)
- // cause llsd serialization to create XML that the llsd deserializer won't parse!
- std::string unicode;
- S32 err = noErr;
- EventParamType actualType = typeUTF8Text;
- UInt32 actualSize = 0;
- char *buffer = NULL;
-
- err = GetEventParameter (mRawKeyEvent, kEventParamKeyUnicodes, typeUTF8Text, &actualType, 0, &actualSize, NULL);
- if(err == noErr)
- {
- // allocate a buffer and get the actual data.
- buffer = new char[actualSize];
- err = GetEventParameter (mRawKeyEvent, kEventParamKeyUnicodes, typeUTF8Text, &actualType, actualSize, &actualSize, buffer);
- if(err == noErr)
- {
- unicode.assign(buffer, actualSize);
- }
- delete[] buffer;
- }
-
- result["unicode"] = unicode;
-#endif
-
+ result["event_type"] = LLSD::Integer(mRawKeyEvent->mEventType);
+ result["event_modifiers"] = LLSD::Integer(mRawKeyEvent->mEventModifiers);
+ result["event_keycode"] = LLSD::Integer(mRawKeyEvent->mEventKeyCode);
+ result["event_chars"] = (mRawKeyEvent->mEventChars) ? LLSD(LLSD::Integer(mRawKeyEvent->mEventChars)) : LLSD();
+ result["event_umodchars"] = (mRawKeyEvent->mEventUnmodChars) ? LLSD(LLSD::Integer(mRawKeyEvent->mEventUnmodChars)) : LLSD();
+ result["event_isrepeat"] = LLSD::Boolean(mRawKeyEvent->mEventRepeat);
}
#endif
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 7e0eb9cf31..875ffe4cd4 100755
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -42,6 +42,7 @@
#include "llgl.h"
#include "llstring.h"
#include "lldir.h"
+#include "llsdutil.h"
#include "llglslshader.h"
// System includes
@@ -2068,6 +2069,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
window_imp->mKeyCharCode = 0; // don't know until wm_char comes in next
window_imp->mKeyScanCode = ( l_param >> 16 ) & 0xff;
window_imp->mKeyVirtualKey = w_param;
+ window_imp->mRawMsg = u_msg;
+ window_imp->mRawWParam = w_param;
+ window_imp->mRawLParam = l_param;
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYDOWN");
{
@@ -2090,6 +2094,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
{
window_imp->mKeyScanCode = ( l_param >> 16 ) & 0xff;
window_imp->mKeyVirtualKey = w_param;
+ window_imp->mRawMsg = u_msg;
+ window_imp->mRawWParam = w_param;
+ window_imp->mRawLParam = l_param;
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYUP");
LL_RECORD_BLOCK_TIME(FTM_KEYHANDLER);
@@ -2177,6 +2184,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_CHAR:
window_imp->mKeyCharCode = w_param;
+ window_imp->mRawMsg = u_msg;
+ window_imp->mRawWParam = w_param;
+ window_imp->mRawLParam = l_param;
// Should really use WM_UNICHAR eventually, but it requires a specific Windows version and I need
// to figure out how that works. - Doug
@@ -3239,6 +3249,9 @@ LLSD LLWindowWin32::getNativeKeyData()
result["scan_code"] = (S32)mKeyScanCode;
result["virtual_key"] = (S32)mKeyVirtualKey;
+ result["msg"] = ll_sd_from_U32(mRawMsg);
+ result["w_param"] = ll_sd_from_U32(mRawWParam);
+ result["l_param"] = ll_sd_from_U32(mRawLParam);
return result;
}
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index 2ca8d48fc7..1a775eadaf 100755
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -126,7 +126,7 @@ protected:
HCURSOR loadColorCursor(LPCTSTR name);
BOOL isValid();
void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
- LLSD getNativeKeyData();
+ virtual LLSD getNativeKeyData();
// Changes display resolution. Returns true if successful
BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
@@ -208,6 +208,9 @@ protected:
U32 mKeyCharCode;
U32 mKeyScanCode;
U32 mKeyVirtualKey;
+ U32 mRawMsg;
+ U32 mRawWParam;
+ U32 mRawLParam;
friend class LLWindowManager;
};
diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt
index 85318aea3b..24eb3947b4 100755
--- a/indra/media_plugins/CMakeLists.txt
+++ b/indra/media_plugins/CMakeLists.txt
@@ -2,16 +2,17 @@
add_subdirectory(base)
-add_subdirectory(webkit)
-
-add_subdirectory(gstreamer010)
+if (LINUX)
+ add_subdirectory(gstreamer010)
+endif (LINUX)
if (WINDOWS OR DARWIN)
add_subdirectory(quicktime)
+ add_subdirectory(cef)
endif (WINDOWS OR DARWIN)
if (WINDOWS)
add_subdirectory(winmmshim)
endif (WINDOWS)
-add_subdirectory(example)
+### add_subdirectory(example)
diff --git a/indra/media_plugins/webkit/CMakeLists.txt b/indra/media_plugins/cef/CMakeLists.txt
index 5a8fe90bdd..1f6163e41e 100755..100644
--- a/indra/media_plugins/webkit/CMakeLists.txt
+++ b/indra/media_plugins/cef/CMakeLists.txt
@@ -1,6 +1,6 @@
# -*- cmake -*-
-project(media_plugin_webkit)
+project(media_plugin_cef)
include(00-Common)
include(LLCommon)
@@ -9,17 +9,14 @@ include(LLPlugin)
include(LLMath)
include(LLRender)
include(LLWindow)
-include(UI)
include(Linking)
include(PluginAPI)
include(MediaPluginBase)
include(OpenGL)
-include(PulseAudio)
-include(WebKitLibPlugin)
+include(CEFPlugin)
include_directories(
- ${PULSEAUDIO_INCLUDE_DIRS}
${LLPLUGIN_INCLUDE_DIRS}
${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
@@ -27,14 +24,14 @@ include_directories(
${LLIMAGE_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS}
- ${LLQTWEBKIT_INCLUDE_DIR}
+ ${CEF_INCLUDE_DIR}
)
include_directories(SYSTEM
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
)
-### media_plugin_webkit
+### media_plugin_cef
if(NOT WORD_SIZE EQUAL 32)
if(WINDOWS)
@@ -44,75 +41,72 @@ if(NOT WORD_SIZE EQUAL 32)
endif(WINDOWS)
endif(NOT WORD_SIZE EQUAL 32)
-set(media_plugin_webkit_SOURCE_FILES
- media_plugin_webkit.cpp
+set(media_plugin_cef_SOURCE_FILES
+ media_plugin_cef.cpp
)
-set(media_plugin_webkit_HEADER_FILES
+set(media_plugin_cef_HEADER_FILES
volume_catcher.h
)
-set(media_plugin_webkit_LINK_LIBRARIES
+set (media_plugin_cef_LINK_LIBRARIES
${LLPLUGIN_LIBRARIES}
${MEDIA_PLUGIN_BASE_LIBRARIES}
${LLCOMMON_LIBRARIES}
- ${WEBKIT_PLUGIN_LIBRARIES}
- ${PLUGIN_API_WINDOWS_LIBRARIES}
- ${PULSEAUDIO_LIBRARIES}
-)
+ ${CEF_PLUGIN_LIBRARIES}
+ ${PLUGIN_API_WINDOWS_LIBRARIES})
+
# Select which VolumeCatcher implementation to use
if (LINUX)
- if (PULSEAUDIO_FOUND)
- list(APPEND media_plugin_webkit_SOURCE_FILES linux_volume_catcher.cpp)
- else (PULSEAUDIO_FOUND)
- list(APPEND media_plugin_webkit_SOURCE_FILES dummy_volume_catcher.cpp)
- endif (PULSEAUDIO_FOUND)
- list(APPEND media_plugin_webkit_LINK_LIBRARIES
- ${UI_LIBRARIES} # for glib/GTK
- )
+ message(FATAL_ERROR "CEF plugin has been enabled for a Linux compile.\n"
+ " Please create a volume_catcher implementation for this platform.")
+
elseif (DARWIN)
- list(APPEND media_plugin_webkit_SOURCE_FILES mac_volume_catcher.cpp)
+ list(APPEND media_plugin_cef_SOURCE_FILES mac_volume_catcher.cpp)
find_library(CORESERVICES_LIBRARY CoreServices)
find_library(AUDIOUNIT_LIBRARY AudioUnit)
- list(APPEND media_plugin_webkit_LINK_LIBRARIES
+ list(APPEND media_plugin_cef_LINK_LIBRARIES
${CORESERVICES_LIBRARY} # for Component Manager calls
${AUDIOUNIT_LIBRARY} # for AudioUnit calls
)
elseif (WINDOWS)
- list(APPEND media_plugin_webkit_SOURCE_FILES windows_volume_catcher.cpp)
+ list(APPEND media_plugin_cef_SOURCE_FILES windows_volume_catcher.cpp)
endif (LINUX)
-set_source_files_properties(${media_plugin_webkit_HEADER_FILES}
+set_source_files_properties(${media_plugin_cef_HEADER_FILES}
PROPERTIES HEADER_FILE_ONLY TRUE)
-list(APPEND media_plugin_webkit_SOURCE_FILES ${media_plugin_webkit_HEADER_FILES})
+list(APPEND media_plugin_cef_SOURCE_FILES ${media_plugin_cef_HEADER_FILES})
-add_library(media_plugin_webkit
+add_library(media_plugin_cef
SHARED
- ${media_plugin_webkit_SOURCE_FILES}
+ ${media_plugin_cef_SOURCE_FILES}
)
-target_link_libraries(media_plugin_webkit ${media_plugin_webkit_LINK_LIBRARIES})
-
-add_dependencies(media_plugin_webkit
+add_dependencies(media_plugin_cef
${LLPLUGIN_LIBRARIES}
${MEDIA_PLUGIN_BASE_LIBRARIES}
${LLCOMMON_LIBRARIES}
)
+target_link_libraries(media_plugin_cef
+ ${media_plugin_cef_LINK_LIBRARIES}
+)
+
if (WINDOWS)
set_target_properties(
- media_plugin_webkit
+ media_plugin_cef
PROPERTIES
- LINK_FLAGS "/MANIFEST:NO"
+ LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /LTCG /NODEFAULTLIB:LIBCMT"
+ LINK_FLAGS_DEBUG "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMTD"
)
endif (WINDOWS)
if (DARWIN)
# Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
set_target_properties(
- media_plugin_webkit
+ media_plugin_cef
PROPERTIES
PREFIX ""
BUILD_WITH_INSTALL_RPATH 1
@@ -120,13 +114,4 @@ if (DARWIN)
LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp"
)
- # copy the webkit dylib to the build directory
-# add_custom_command(
-# TARGET media_plugin_webkit POST_BUILD
-# # OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/libllqtwebkit.dylib
-# COMMAND ${CMAKE_COMMAND} -E copy ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
-# DEPENDS media_plugin_webkit ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib
-# )
-
endif (DARWIN)
-
diff --git a/indra/media_plugins/webkit/mac_volume_catcher.cpp b/indra/media_plugins/cef/mac_volume_catcher.cpp
index 73e5bf3da3..dddb9c2077 100755..100644
--- a/indra/media_plugins/webkit/mac_volume_catcher.cpp
+++ b/indra/media_plugins/cef/mac_volume_catcher.cpp
@@ -6,7 +6,7 @@
* $LicenseInfo:firstyear=2010&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;
diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp
new file mode 100644
index 0000000000..a2479cc946
--- /dev/null
+++ b/indra/media_plugins/cef/media_plugin_cef.cpp
@@ -0,0 +1,885 @@
+/**
+* @file media_plugin_cef.cpp
+* @brief CEF (Chromium Embedding Framework) plugin for LLMedia API plugin system
+*
+* @cond
+* $LicenseInfo:firstyear=2008&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2010, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+* @endcond
+*/
+
+#include "linden_common.h"
+#include "indra_constants.h" // for indra keyboard codes
+
+#include "llgl.h"
+#include "llsdutil.h"
+#include "llplugininstance.h"
+#include "llpluginmessage.h"
+#include "llpluginmessageclasses.h"
+#include "media_plugin_base.h"
+
+#include "boost/function.hpp"
+#include "boost/bind.hpp"
+#include "llCEFLib.h"
+#include "volume_catcher.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//
+class MediaPluginCEF :
+ public MediaPluginBase
+{
+public:
+ MediaPluginCEF(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
+ ~MediaPluginCEF();
+
+ /*virtual*/
+ void receiveMessage(const char* message_string);
+
+private:
+ bool init();
+
+ void onPageChangedCallback(unsigned char* pixels, int x, int y, int width, int height, bool is_popup);
+ void onCustomSchemeURLCallback(std::string url);
+ void onConsoleMessageCallback(std::string message, std::string source, int line);
+ void onStatusMessageCallback(std::string value);
+ void onTitleChangeCallback(std::string title);
+ void onLoadStartCallback();
+ void onRequestExitCallback();
+ void onLoadEndCallback(int httpStatusCode);
+ void onAddressChangeCallback(std::string url);
+ void onNavigateURLCallback(std::string url, std::string target);
+ bool onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password);
+ void onCursorChangedCallback(LLCEFLib::ECursorType type, unsigned int handle);
+ void onFileDownloadCallback(std::string filename);
+
+ void postDebugMessage(const std::string& msg);
+ void authResponse(LLPluginMessage &message);
+
+ LLCEFLib::EKeyboardModifier decodeModifiers(std::string &modifiers);
+ void deserializeKeyboardData(LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers);
+ void keyEvent(LLCEFLib::EKeyEvent key_event, int key, LLCEFLib::EKeyboardModifier modifiers, LLSD native_key_data);
+ void unicodeInput(const std::string &utf8str, LLCEFLib::EKeyboardModifier modifiers, LLSD native_key_data);
+
+ void checkEditState();
+ void setVolume(F32 vol);
+
+ bool mEnableMediaPluginDebugging;
+ std::string mHostLanguage;
+ bool mCookiesEnabled;
+ bool mPluginsEnabled;
+ bool mJavascriptEnabled;
+ std::string mUserAgentSubtring;
+ std::string mAuthUsername;
+ std::string mAuthPassword;
+ bool mAuthOK;
+ bool mCanCut;
+ bool mCanCopy;
+ bool mCanPaste;
+ std::string mCachePath;
+ std::string mCookiePath;
+ LLCEFLib* mLLCEFLib;
+
+ VolumeCatcher mVolumeCatcher;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+MediaPluginCEF::MediaPluginCEF(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) :
+MediaPluginBase(host_send_func, host_user_data)
+{
+ mWidth = 0;
+ mHeight = 0;
+ mDepth = 4;
+ mPixels = 0;
+ mEnableMediaPluginDebugging = true;
+ mHostLanguage = "en";
+ mCookiesEnabled = true;
+ mPluginsEnabled = false;
+ mJavascriptEnabled = true;
+ mUserAgentSubtring = "";
+ mAuthUsername = "";
+ mAuthPassword = "";
+ mAuthOK = false;
+ mCanCut = false;
+ mCanCopy = false;
+ mCanPaste = false;
+ mCachePath = "";
+ mCookiePath = "";
+ mLLCEFLib = new LLCEFLib();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+MediaPluginCEF::~MediaPluginCEF()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginCEF::postDebugMessage(const std::string& msg)
+{
+ if (mEnableMediaPluginDebugging)
+ {
+ std::stringstream str;
+ str << "@Media Msg> " << msg;
+
+ LLPluginMessage debug_message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "debug_message");
+ debug_message.setValue("message_text", str.str());
+ debug_message.setValue("message_level", "info");
+ sendMessage(debug_message);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int x, int y, int width, int height, bool is_popup)
+{
+ if (mPixels && pixels)
+ {
+ if (is_popup)
+ {
+ for (int line = 0; line < height; ++line)
+ {
+ int inverted_y = mHeight - y - height;
+ int src = line * width * mDepth;
+ int dst = (inverted_y + line) * mWidth * mDepth + x * mDepth;
+
+ if (dst + width * mDepth < mWidth * mHeight * mDepth)
+ {
+ memcpy(mPixels + dst, pixels + src, width * mDepth);
+ }
+ }
+ }
+ else
+ {
+ if (mWidth == width && mHeight == height)
+ {
+ memcpy(mPixels, pixels, mWidth * mHeight * mDepth);
+ }
+
+ }
+ setDirty(0, 0, mWidth, mHeight);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginCEF::onConsoleMessageCallback(std::string message, std::string source, int line)
+{
+ std::stringstream str;
+ str << "Console message: " << message << " in file(" << source << ") at line " << line;
+ postDebugMessage(str.str());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginCEF::onStatusMessageCallback(std::string value)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "status_text");
+ message.setValue("status", value);
+ sendMessage(message);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginCEF::onTitleChangeCallback(std::string title)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
+ message.setValue("name", title);
+ sendMessage(message);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginCEF::onLoadStartCallback()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin");
+ //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed?
+ message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack());
+ message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward());
+ sendMessage(message);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginCEF::onRequestExitCallback()
+{
+ mLLCEFLib->shutdown();
+
+ LLPluginMessage message("base", "goodbye");
+ sendMessage(message);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginCEF::onLoadEndCallback(int httpStatusCode)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete");
+ //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed?
+ message.setValueS32("result_code", httpStatusCode);
+ message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack());
+ message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward());
+ sendMessage(message);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginCEF::onAddressChangeCallback(std::string url)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed");
+ message.setValue("uri", url);
+ sendMessage(message);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginCEF::onNavigateURLCallback(std::string url, std::string target)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href");
+ message.setValue("uri", url);
+ message.setValue("target", target);
+ message.setValue("uuid", ""); // not used right now
+ sendMessage(message);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginCEF::onCustomSchemeURLCallback(std::string url)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow");
+ message.setValue("uri", url);
+ message.setValue("nav_type", "clicked"); // TODO: differentiate between click and navigate to
+ sendMessage(message);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool MediaPluginCEF::onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password)
+{
+ mAuthOK = false;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_request");
+ message.setValue("url", host);
+ message.setValue("realm", realm);
+ message.setValueBoolean("blocking_request", true);
+
+ // The "blocking_request" key in the message means this sendMessage call will block until a response is received.
+ sendMessage(message);
+
+ if (mAuthOK)
+ {
+ username = mAuthUsername;
+ password = mAuthPassword;
+ }
+
+ return mAuthOK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginCEF::onFileDownloadCallback(const std::string filename)
+{
+ mAuthOK = false;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "file_download");
+ message.setValue("filename", filename);
+
+ sendMessage(message);
+}
+
+void MediaPluginCEF::onCursorChangedCallback(LLCEFLib::ECursorType type, unsigned int handle)
+{
+ std::string name = "";
+
+ switch (type)
+ {
+ case LLCEFLib::CT_POINTER:
+ name = "arrow";
+ break;
+ case LLCEFLib::CT_IBEAM:
+ name = "ibeam";
+ break;
+ case LLCEFLib::CT_NORTHSOUTHRESIZE:
+ name = "splitv";
+ break;
+ case LLCEFLib::CT_EASTWESTRESIZE:
+ name = "splith";
+ break;
+ case LLCEFLib::CT_HAND:
+ name = "hand";
+ break;
+
+ default:
+ LL_WARNS() << "Unknown cursor ID: " << (int)type << LL_ENDL;
+ break;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "cursor_changed");
+ message.setValue("name", name);
+ sendMessage(message);
+}
+
+void MediaPluginCEF::authResponse(LLPluginMessage &message)
+{
+ mAuthOK = message.getValueBoolean("ok");
+ if (mAuthOK)
+ {
+ mAuthUsername = message.getValue("username");
+ mAuthPassword = message.getValue("password");
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginCEF::receiveMessage(const char* message_string)
+{
+ // std::cerr << "MediaPluginCEF::receiveMessage: received message: \"" << message_string << "\"" << std::endl;
+ LLPluginMessage message_in;
+
+ if (message_in.parse(message_string) >= 0)
+ {
+ std::string message_class = message_in.getClass();
+ std::string message_name = message_in.getName();
+ if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
+ {
+ if (message_name == "init")
+ {
+ LLPluginMessage message("base", "init_response");
+ LLSD versions = LLSD::emptyMap();
+ versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
+ versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
+ versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION;
+ message.setValueLLSD("versions", versions);
+
+ std::string plugin_version = "CEF plugin 1.1.3";
+ message.setValue("plugin_version", plugin_version);
+ sendMessage(message);
+ }
+ else if (message_name == "idle")
+ {
+ mLLCEFLib->update();
+
+ mVolumeCatcher.pump();
+ // this seems bad but unless the state changes (it won't until we figure out
+ // how to get CEF to tell us if copy/cut/paste is available) then this function
+ // will return immediately
+ checkEditState();
+ }
+ else if (message_name == "cleanup")
+ {
+ mLLCEFLib->requestExit();
+ }
+ 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)
+ {
+ mPixels = NULL;
+ mTextureSegmentName.clear();
+ }
+ mSharedSegments.erase(iter);
+ }
+ else
+ {
+ }
+
+ LLPluginMessage message("base", "shm_remove_response");
+ message.setValue("name", name);
+ sendMessage(message);
+ }
+ else
+ {
+ }
+ }
+ else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+ {
+ if (message_name == "init")
+ {
+ // event callbacks from LLCefLib
+ mLLCEFLib->setOnPageChangedCallback(boost::bind(&MediaPluginCEF::onPageChangedCallback, this, _1, _2, _3, _4, _5, _6));
+ mLLCEFLib->setOnCustomSchemeURLCallback(boost::bind(&MediaPluginCEF::onCustomSchemeURLCallback, this, _1));
+ mLLCEFLib->setOnConsoleMessageCallback(boost::bind(&MediaPluginCEF::onConsoleMessageCallback, this, _1, _2, _3));
+ mLLCEFLib->setOnStatusMessageCallback(boost::bind(&MediaPluginCEF::onStatusMessageCallback, this, _1));
+ mLLCEFLib->setOnTitleChangeCallback(boost::bind(&MediaPluginCEF::onTitleChangeCallback, this, _1));
+ mLLCEFLib->setOnLoadStartCallback(boost::bind(&MediaPluginCEF::onLoadStartCallback, this));
+ mLLCEFLib->setOnLoadEndCallback(boost::bind(&MediaPluginCEF::onLoadEndCallback, this, _1));
+ mLLCEFLib->setOnAddressChangeCallback(boost::bind(&MediaPluginCEF::onAddressChangeCallback, this, _1));
+ mLLCEFLib->setOnNavigateURLCallback(boost::bind(&MediaPluginCEF::onNavigateURLCallback, this, _1, _2));
+ mLLCEFLib->setOnHTTPAuthCallback(boost::bind(&MediaPluginCEF::onHTTPAuthCallback, this, _1, _2, _3, _4));
+ mLLCEFLib->setOnFileDownloadCallback(boost::bind(&MediaPluginCEF::onFileDownloadCallback, this, _1));
+ mLLCEFLib->setOnCursorChangedCallback(boost::bind(&MediaPluginCEF::onCursorChangedCallback, this, _1, _2));
+ mLLCEFLib->setOnRequestExitCallback(boost::bind(&MediaPluginCEF::onRequestExitCallback, this));
+
+ LLCEFLib::LLCEFLibSettings settings;
+ settings.initial_width = 1024;
+ settings.initial_height = 1024;
+ settings.plugins_enabled = mPluginsEnabled;
+ settings.javascript_enabled = mJavascriptEnabled;
+ settings.cookies_enabled = mCookiesEnabled;
+ settings.cookie_store_path = mCookiePath;
+ settings.cache_enabled = true;
+ settings.cache_path = mCachePath;
+ settings.accept_language_list = mHostLanguage;
+ settings.user_agent_substring = mLLCEFLib->makeCompatibleUserAgentString(mUserAgentSubtring);
+
+ bool result = mLLCEFLib->init(settings);
+ if (!result)
+ {
+ // if this fails, the media system in viewer will put up a message
+ }
+
+ // Plugin gets to decide the texture parameters to use.
+ mDepth = 4;
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
+ message.setValueS32("default_width", 1024);
+ message.setValueS32("default_height", 1024);
+ message.setValueS32("depth", mDepth);
+ message.setValueU32("internalformat", GL_RGB);
+ message.setValueU32("format", GL_BGRA);
+ message.setValueU32("type", GL_UNSIGNED_BYTE);
+ message.setValueBoolean("coords_opengl", true);
+ sendMessage(message);
+ }
+ else if (message_name == "set_user_data_path")
+ {
+ std::string user_data_path_cache = message_in.getValue("cache_path");
+ std::string user_data_path_cookies = message_in.getValue("cookies_path");
+ mCachePath = user_data_path_cache + "cef_cache";
+ mCookiePath = user_data_path_cookies + "cef_cookies";
+ }
+ else if (message_name == "size_change")
+ {
+ std::string name = message_in.getValue("name");
+ S32 width = message_in.getValueS32("width");
+ S32 height = message_in.getValueS32("height");
+ S32 texture_width = message_in.getValueS32("texture_width");
+ S32 texture_height = message_in.getValueS32("texture_height");
+
+ if (!name.empty())
+ {
+ // Find the shared memory region with this name
+ SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+ if (iter != mSharedSegments.end())
+ {
+ mPixels = (unsigned char*)iter->second.mAddress;
+ mWidth = width;
+ mHeight = height;
+
+ mTextureWidth = texture_width;
+ mTextureHeight = texture_height;
+ };
+ };
+
+ mLLCEFLib->setSize(mWidth, mHeight);
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
+ message.setValue("name", name);
+ message.setValueS32("width", width);
+ message.setValueS32("height", height);
+ message.setValueS32("texture_width", texture_width);
+ message.setValueS32("texture_height", texture_height);
+ sendMessage(message);
+
+ }
+ else if (message_name == "set_language_code")
+ {
+ mHostLanguage = message_in.getValue("language");
+ }
+ else if (message_name == "load_uri")
+ {
+ std::string uri = message_in.getValue("uri");
+ mLLCEFLib->navigate(uri);
+ }
+ else if (message_name == "set_cookie")
+ {
+ std::string uri = message_in.getValue("uri");
+ std::string name = message_in.getValue("name");
+ std::string value = message_in.getValue("value");
+ std::string domain = message_in.getValue("domain");
+ std::string path = message_in.getValue("path");
+ bool httponly = message_in.getValueBoolean("httponly");
+ bool secure = message_in.getValueBoolean("secure");
+ mLLCEFLib->setCookie(uri, name, value, domain, path, httponly, secure);
+ }
+ 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");
+
+ // only even send left mouse button events to LLCEFLib
+ // (partially prompted by crash in OS X CEF when sending right button events)
+ // we catch the right click in viewer and display our own context menu anyway
+ S32 button = message_in.getValueS32("button");
+ LLCEFLib::EMouseButton btn = LLCEFLib::MB_MOUSE_BUTTON_LEFT;
+
+ if (event == "down" && button == 0)
+ {
+ mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_DOWN, x, y);
+ mLLCEFLib->setFocus(true);
+
+ std::stringstream str;
+ str << "Mouse down at = " << x << ", " << y;
+ postDebugMessage(str.str());
+ }
+ else if (event == "up" && button == 0)
+ {
+ mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_UP, x, y);
+
+ std::stringstream str;
+ str << "Mouse up at = " << x << ", " << y;
+ postDebugMessage(str.str());
+ }
+ else if (event == "double_click")
+ {
+ mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_DOUBLE_CLICK, x, y);
+ }
+ else
+ {
+ mLLCEFLib->mouseMove(x, y);
+ }
+ }
+ else if (message_name == "scroll_event")
+ {
+ S32 x = message_in.getValueS32("x");
+ S32 y = message_in.getValueS32("y");
+ const int scaling_factor = 40;
+ y *= -scaling_factor;
+
+ mLLCEFLib->mouseWheel(x, y);
+ }
+ else if (message_name == "text_event")
+ {
+ std::string text = message_in.getValue("text");
+ std::string modifiers = message_in.getValue("modifiers");
+ LLSD native_key_data = message_in.getValueLLSD("native_key_data");
+
+ unicodeInput(text, decodeModifiers(modifiers), native_key_data);
+ }
+ else if (message_name == "key_event")
+ {
+#if LL_DARWIN
+ std::string event = message_in.getValue("event");
+ S32 key = message_in.getValueS32("key");
+ LLSD native_key_data = message_in.getValueLLSD("native_key_data");
+
+#if 0
+ if (event == "down")
+ {
+ //mLLCEFLib->keyPress(key, true);
+ mLLCEFLib->keyboardEvent(LLCEFLib::KE_KEY_DOWN, (uint32_t)key, 0, LLCEFLib::KM_MODIFIER_NONE, 0, 0, 0);
+
+ }
+ else if (event == "up")
+ {
+ //mLLCEFLib->keyPress(key, false);
+ mLLCEFLib->keyboardEvent(LLCEFLib::KE_KEY_UP, (uint32_t)key, 0, LLCEFLib::KM_MODIFIER_NONE, 0, 0, 0);
+ }
+#else
+ // Treat unknown events as key-up for safety.
+ LLCEFLib::EKeyEvent key_event = LLCEFLib::KE_KEY_UP;
+ if (event == "down")
+ {
+ key_event = LLCEFLib::KE_KEY_DOWN;
+ }
+ else if (event == "repeat")
+ {
+ key_event = LLCEFLib::KE_KEY_REPEAT;
+ }
+
+ keyEvent(key_event, key, LLCEFLib::KM_MODIFIER_NONE, native_key_data);
+
+#endif
+#elif LL_WINDOWS
+ std::string event = message_in.getValue("event");
+ S32 key = message_in.getValueS32("key");
+ std::string modifiers = message_in.getValue("modifiers");
+ LLSD native_key_data = message_in.getValueLLSD("native_key_data");
+
+ // Treat unknown events as key-up for safety.
+ LLCEFLib::EKeyEvent key_event = LLCEFLib::KE_KEY_UP;
+ if (event == "down")
+ {
+ key_event = LLCEFLib::KE_KEY_DOWN;
+ }
+ else if (event == "repeat")
+ {
+ key_event = LLCEFLib::KE_KEY_REPEAT;
+ }
+
+ keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data);
+#endif
+ }
+ else if (message_name == "enable_media_plugin_debugging")
+ {
+ mEnableMediaPluginDebugging = message_in.getValueBoolean("enable");
+ }
+ if (message_name == "auth_response")
+ {
+ authResponse(message_in);
+ }
+ if (message_name == "edit_cut")
+ {
+ mLLCEFLib->editCut();
+ }
+ if (message_name == "edit_copy")
+ {
+ mLLCEFLib->editCopy();
+ }
+ if (message_name == "edit_paste")
+ {
+ mLLCEFLib->editPaste();
+ }
+ }
+ else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
+ {
+ if (message_name == "set_page_zoom_factor")
+ {
+ F32 factor = (F32)message_in.getValueReal("factor");
+ mLLCEFLib->setPageZoom(factor);
+ }
+ if (message_name == "browse_stop")
+ {
+ mLLCEFLib->stop();
+ }
+ else if (message_name == "browse_reload")
+ {
+ bool ignore_cache = true;
+ mLLCEFLib->reload(ignore_cache);
+ }
+ else if (message_name == "browse_forward")
+ {
+ mLLCEFLib->goForward();
+ }
+ else if (message_name == "browse_back")
+ {
+ mLLCEFLib->goBack();
+ }
+ else if (message_name == "cookies_enabled")
+ {
+ mCookiesEnabled = message_in.getValueBoolean("enable");
+ }
+ else if (message_name == "set_user_agent")
+ {
+ mUserAgentSubtring = message_in.getValue("user_agent");
+ }
+ else if (message_name == "show_web_inspector")
+ {
+ mLLCEFLib->showDevTools(true);
+ }
+ else if (message_name == "plugins_enabled")
+ {
+ mPluginsEnabled = message_in.getValueBoolean("enable");
+ }
+ else if (message_name == "javascript_enabled")
+ {
+ mJavascriptEnabled = message_in.getValueBoolean("enable");
+ }
+ }
+ else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+ {
+ if (message_name == "set_volume")
+ {
+ F32 volume = (F32)message_in.getValueReal("volume");
+ setVolume(volume);
+ }
+ }
+ else
+ {
+ };
+ }
+}
+
+LLCEFLib::EKeyboardModifier MediaPluginCEF::decodeModifiers(std::string &modifiers)
+{
+ int result = 0;
+
+ if (modifiers.find("shift") != std::string::npos)
+ result |= LLCEFLib::KM_MODIFIER_SHIFT;
+
+ if (modifiers.find("alt") != std::string::npos)
+ result |= LLCEFLib::KM_MODIFIER_ALT;
+
+ if (modifiers.find("control") != std::string::npos)
+ result |= LLCEFLib::KM_MODIFIER_CONTROL;
+
+ if (modifiers.find("meta") != std::string::npos)
+ result |= LLCEFLib::KM_MODIFIER_META;
+
+ return (LLCEFLib::EKeyboardModifier)result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginCEF::deserializeKeyboardData(LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers)
+{
+ native_scan_code = 0;
+ native_virtual_key = 0;
+ native_modifiers = 0;
+
+ if (native_key_data.isMap())
+ {
+#if LL_DARWIN
+ native_scan_code = (uint32_t)(native_key_data["char_code"].asInteger());
+ native_virtual_key = (uint32_t)(native_key_data["key_code"].asInteger());
+ native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger());
+#elif LL_WINDOWS
+ native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger());
+ native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger());
+ // TODO: I don't think we need to do anything with native modifiers here -- please verify
+#endif
+ };
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginCEF::keyEvent(LLCEFLib::EKeyEvent key_event, int key, LLCEFLib::EKeyboardModifier modifiers_x, LLSD native_key_data = LLSD::emptyMap())
+{
+#if LL_DARWIN
+
+ if (!native_key_data.has("event_type") ||
+ !native_key_data.has("event_modifiers") ||
+ !native_key_data.has("event_keycode") ||
+ !native_key_data.has("event_isrepeat"))
+ return;
+
+ uint32_t eventType = native_key_data["event_type"].asInteger();
+ if (!eventType)
+ return;
+ uint32_t eventModifiers = native_key_data["event_modifiers"].asInteger();
+ uint32_t eventKeycode = native_key_data["event_keycode"].asInteger();
+ char eventChars = static_cast<char>(native_key_data["event_chars"].isUndefined() ? 0 : native_key_data["event_chars"].asInteger());
+ char eventUChars = static_cast<char>(native_key_data["event_umodchars"].isUndefined() ? 0 : native_key_data["event_umodchars"].asInteger());
+ bool eventIsRepeat = native_key_data["event_isrepeat"].asBoolean();
+
+ mLLCEFLib->keyboardEventOSX(eventType, eventModifiers, (eventChars) ? &eventChars : NULL,
+ (eventUChars) ? &eventUChars : NULL, eventIsRepeat, eventKeycode);
+
+#elif LL_WINDOWS
+ U32 msg = ll_U32_from_sd(native_key_data["msg"]);
+ U32 wparam = ll_U32_from_sd(native_key_data["w_param"]);
+ U64 lparam = ll_U32_from_sd(native_key_data["l_param"]);
+
+ mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam);
+#endif
+};
+
+void MediaPluginCEF::unicodeInput(const std::string &utf8str, LLCEFLib::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap())
+{
+#if LL_DARWIN
+ //mLLCEFLib->keyPress(utf8str[0], true);
+ //mLLCEFLib->keyboardEvent(LLCEFLib::KE_KEY_DOWN, (uint32_t)(utf8str[0]), 0, LLCEFLib::KM_MODIFIER_NONE, 0, 0, 0);
+ if (!native_key_data.has("event_chars") || !native_key_data.has("event_umodchars") ||
+ !native_key_data.has("event_keycode") || !native_key_data.has("event_modifiers"))
+ return;
+ uint32_t unicodeChar = native_key_data["event_chars"].asInteger();
+ uint32_t unmodifiedChar = native_key_data["event_umodchars"].asInteger();
+ uint32_t keyCode = native_key_data["event_keycode"].asInteger();
+ uint32_t rawmodifiers = native_key_data["event_modifiers"].asInteger();
+
+ mLLCEFLib->injectUnicodeText(unicodeChar, unmodifiedChar, keyCode, rawmodifiers);
+
+#elif LL_WINDOWS
+ U32 msg = ll_U32_from_sd(native_key_data["msg"]);
+ U32 wparam = ll_U32_from_sd(native_key_data["w_param"]);
+ U64 lparam = ll_U32_from_sd(native_key_data["l_param"]);
+ mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam);
+#endif
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginCEF::checkEditState()
+{
+ bool can_cut = mLLCEFLib->editCanCut();
+ bool can_copy = mLLCEFLib->editCanCopy();
+ bool can_paste = mLLCEFLib->editCanPaste();
+
+ if ((can_cut != mCanCut) || (can_copy != mCanCopy) || (can_paste != mCanPaste))
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_state");
+
+ if (can_cut != mCanCut)
+ {
+ mCanCut = can_cut;
+ message.setValueBoolean("cut", can_cut);
+ }
+
+ if (can_copy != mCanCopy)
+ {
+ mCanCopy = can_copy;
+ message.setValueBoolean("copy", can_copy);
+ }
+
+ if (can_paste != mCanPaste)
+ {
+ mCanPaste = can_paste;
+ message.setValueBoolean("paste", can_paste);
+ }
+
+ sendMessage(message);
+ }
+}
+
+void MediaPluginCEF::setVolume(F32 vol)
+{
+ mVolumeCatcher.setVolume(vol);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool MediaPluginCEF::init()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
+ message.setValue("name", "CEF Plugin");
+ sendMessage(message);
+
+ return true;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func,
+ void* host_user_data,
+ LLPluginInstance::sendMessageFunction *plugin_send_func,
+ void **plugin_user_data)
+{
+ MediaPluginCEF* self = new MediaPluginCEF(host_send_func, host_user_data);
+ *plugin_send_func = MediaPluginCEF::staticReceiveMessage;
+ *plugin_user_data = (void*)self;
+
+ return 0;
+}
diff --git a/indra/media_plugins/webkit/volume_catcher.h b/indra/media_plugins/cef/volume_catcher.h
index 337f2913d3..337f2913d3 100755..100644
--- a/indra/media_plugins/webkit/volume_catcher.h
+++ b/indra/media_plugins/cef/volume_catcher.h
diff --git a/indra/media_plugins/webkit/windows_volume_catcher.cpp b/indra/media_plugins/cef/windows_volume_catcher.cpp
index 0cfb810906..0cfb810906 100755..100644
--- a/indra/media_plugins/webkit/windows_volume_catcher.cpp
+++ b/indra/media_plugins/cef/windows_volume_catcher.cpp
diff --git a/indra/media_plugins/quicktime/CMakeLists.txt b/indra/media_plugins/quicktime/CMakeLists.txt
index 58391007ff..d7a1874bf3 100755
--- a/indra/media_plugins/quicktime/CMakeLists.txt
+++ b/indra/media_plugins/quicktime/CMakeLists.txt
@@ -63,7 +63,8 @@ if (WINDOWS)
set_target_properties(
media_plugin_quicktime
PROPERTIES
- LINK_FLAGS "/MANIFEST:NO"
+ LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMT"
+ LINK_FLAGS_DEBUG "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMTD"
)
endif (WINDOWS)
diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
index ff1ed8bfbc..7ef5a0fe44 100755
--- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
+++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
@@ -837,7 +837,9 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
else if(message_name == "cleanup")
{
// TODO: clean up here
- }
+ LLPluginMessage message("base", "goodbye");
+ sendMessage(message);
+ }
else if(message_name == "shm_added")
{
SharedSegmentInfo info;
diff --git a/indra/media_plugins/webkit/dummy_volume_catcher.cpp b/indra/media_plugins/webkit/dummy_volume_catcher.cpp
deleted file mode 100755
index d54b31b2ae..0000000000
--- a/indra/media_plugins/webkit/dummy_volume_catcher.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * @file dummy_volume_catcher.cpp
- * @brief A null implementation of the "VolumeCatcher" class for platforms where it's not implemented yet.
- *
- * @cond
- * $LicenseInfo:firstyear=2010&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 "volume_catcher.h"
-
-
-class VolumeCatcherImpl
-{
-};
-
-/////////////////////////////////////////////////////
-
-VolumeCatcher::VolumeCatcher()
-{
- pimpl = NULL;
-}
-
-VolumeCatcher::~VolumeCatcher()
-{
-}
-
-void VolumeCatcher::setVolume(F32 volume)
-{
-}
-
-void VolumeCatcher::setPan(F32 pan)
-{
-}
-
-void VolumeCatcher::pump()
-{
-}
-
diff --git a/indra/media_plugins/webkit/linux_volume_catcher.cpp b/indra/media_plugins/webkit/linux_volume_catcher.cpp
deleted file mode 100755
index 91be3a89e9..0000000000
--- a/indra/media_plugins/webkit/linux_volume_catcher.cpp
+++ /dev/null
@@ -1,468 +0,0 @@
-/**
- * @file linux_volume_catcher.cpp
- * @brief A Linux-specific, PulseAudio-specific hack to detect and volume-adjust new audio sources
- *
- * @cond
- * $LicenseInfo:firstyear=2010&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
- */
-
-/*
- The high-level design is as follows:
- 1) Connect to the PulseAudio daemon
- 2) Watch for the creation of new audio players connecting to the daemon (this includes ALSA clients running on the PulseAudio emulation layer, such as Flash plugins)
- 3) Examine any new audio player's PID to see if it belongs to our own process
- 4) If so, tell PA to adjust the volume of that audio player ('sink input' in PA parlance)
- 5) Keep a list of all living audio players that we care about, adjust the volumes of all of them when we get a new setVolume() call
- */
-
-#include "linden_common.h"
-
-#include "volume_catcher.h"
-
-
-extern "C" {
-#include <glib.h>
-#include <glib-object.h>
-
-#include <pulse/introspect.h>
-#include <pulse/context.h>
-#include <pulse/subscribe.h>
-#include <pulse/glib-mainloop.h> // There's no special reason why we want the *glib* PA mainloop, but the generic polling implementation seems broken.
-
-#include "apr_pools.h"
-#include "apr_dso.h"
-}
-
-////////////////////////////////////////////////////
-
-#define DEBUGMSG(...) do {} while(0)
-#define INFOMSG(...) do {} while(0)
-#define WARNMSG(...) do {} while(0)
-
-#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) RTN (*ll##PASYM)(__VA_ARGS__) = NULL
-#include "linux_volume_catcher_pa_syms.inc"
-#include "linux_volume_catcher_paglib_syms.inc"
-#undef LL_PA_SYM
-
-static bool sSymsGrabbed = false;
-static apr_pool_t *sSymPADSOMemoryPool = NULL;
-static apr_dso_handle_t *sSymPADSOHandleG = NULL;
-
-bool grab_pa_syms(std::string pulse_dso_name)
-{
- if (sSymsGrabbed)
- {
- // already have grabbed good syms
- return true;
- }
-
- bool sym_error = false;
- bool rtn = false;
- 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)
-
- //attempt to load the shared library
- apr_pool_create(&sSymPADSOMemoryPool, NULL);
-
- if ( APR_SUCCESS == (rv = apr_dso_load(&sSymPADSOHandle,
- pulse_dso_name.c_str(),
- sSymPADSOMemoryPool) ))
- {
- INFOMSG("Found DSO: %s", pulse_dso_name.c_str());
-
-#include "linux_volume_catcher_pa_syms.inc"
-#include "linux_volume_catcher_paglib_syms.inc"
-
- if ( sSymPADSOHandle )
- {
- sSymPADSOHandleG = sSymPADSOHandle;
- sSymPADSOHandle = NULL;
- }
-
- rtn = !sym_error;
- }
- else
- {
- INFOMSG("Couldn't load DSO: %s", pulse_dso_name.c_str());
- rtn = false; // failure
- }
-
- if (sym_error)
- {
- WARNMSG("Failed to find necessary symbols in PulseAudio libraries.");
- }
-#undef LL_PA_SYM
-
- sSymsGrabbed = rtn;
- return rtn;
-}
-
-
-void ungrab_pa_syms()
-{
- // should be safe to call regardless of whether we've
- // actually grabbed syms.
-
- if ( sSymPADSOHandleG )
- {
- apr_dso_unload(sSymPADSOHandleG);
- sSymPADSOHandleG = NULL;
- }
-
- if ( sSymPADSOMemoryPool )
- {
- apr_pool_destroy(sSymPADSOMemoryPool);
- sSymPADSOMemoryPool = NULL;
- }
-
- // NULL-out all of the symbols we'd grabbed
-#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{ll##PASYM = NULL;}while(0)
-#include "linux_volume_catcher_pa_syms.inc"
-#include "linux_volume_catcher_paglib_syms.inc"
-#undef LL_PA_SYM
-
- sSymsGrabbed = false;
-}
-////////////////////////////////////////////////////
-
-// PulseAudio requires a chain of callbacks with C linkage
-extern "C" {
- void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *i, int eol, void *userdata);
- void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata);
- void callback_context_state(pa_context *context, void *userdata);
-}
-
-
-class VolumeCatcherImpl
-{
-public:
- VolumeCatcherImpl();
- ~VolumeCatcherImpl();
-
- void setVolume(F32 volume);
- void pump(void);
-
- // for internal use - can't be private because used from our C callbacks
-
- bool loadsyms(std::string pulse_dso_name);
- void init();
- void cleanup();
-
- void update_all_volumes(F32 volume);
- void update_index_volume(U32 index, F32 volume);
- void connected_okay();
-
- std::set<U32> mSinkInputIndices;
- std::map<U32,U32> mSinkInputNumChannels;
- F32 mDesiredVolume;
- pa_glib_mainloop *mMainloop;
- pa_context *mPAContext;
- bool mConnected;
- bool mGotSyms;
-};
-
-VolumeCatcherImpl::VolumeCatcherImpl()
- : mDesiredVolume(0.0f),
- mMainloop(NULL),
- mPAContext(NULL),
- mConnected(false),
- mGotSyms(false)
-{
- init();
-}
-
-VolumeCatcherImpl::~VolumeCatcherImpl()
-{
- cleanup();
-}
-
-bool VolumeCatcherImpl::loadsyms(std::string pulse_dso_name)
-{
- return grab_pa_syms(pulse_dso_name);
-}
-
-void VolumeCatcherImpl::init()
-{
- // try to be as defensive as possible because PA's interface is a
- // bit fragile and (for our purposes) we'd rather simply not function
- // than crash
-
- // we cheat and rely upon libpulse-mainloop-glib.so.0 to pull-in
- // libpulse.so.0 - this isn't a great assumption, and the two DSOs should
- // probably be loaded separately. Our Linux DSO framework needs refactoring,
- // we do this sort of thing a lot with practically identical logic...
- 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");
- llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ID, "com.secondlife.viewer.mediaplugvoladjust");
- llpa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "SL Plugin Volume Adjuster");
- llpa_proplist_sets(proplist, PA_PROP_APPLICATION_VERSION, "1");
-
- // plain old pa_context_new() is broken!
- mPAContext = llpa_context_new_with_proplist(api, NULL, proplist);
- llpa_proplist_free(proplist);
- }
- }
- }
-
- // Now we've set up a PA context and mainloop, try connecting the
- // PA context to a PA daemon.
- if (mPAContext)
- {
- llpa_context_set_state_callback(mPAContext, callback_context_state, this);
- pa_context_flags_t cflags = (pa_context_flags)0; // maybe add PA_CONTEXT_NOAUTOSPAWN?
- if (llpa_context_connect(mPAContext, NULL, cflags, NULL) >= 0)
- {
- // Okay! We haven't definitely connected, but we
- // haven't definitely failed yet.
- }
- else
- {
- // Failed to connect to PA manager... we'll leave
- // things like that. Perhaps we should try again later.
- }
- }
-}
-
-void VolumeCatcherImpl::cleanup()
-{
- mConnected = false;
-
- if (mGotSyms && mPAContext)
- {
- llpa_context_disconnect(mPAContext);
- llpa_context_unref(mPAContext);
- }
- mPAContext = NULL;
-
- if (mGotSyms && mMainloop)
- {
- llpa_glib_mainloop_free(mMainloop);
- }
- mMainloop = NULL;
-}
-
-void VolumeCatcherImpl::setVolume(F32 volume)
-{
- mDesiredVolume = volume;
-
- if (!mGotSyms) return;
-
- if (mConnected && mPAContext)
- {
- update_all_volumes(mDesiredVolume);
- }
-
- pump();
-}
-
-void VolumeCatcherImpl::pump()
-{
- gboolean may_block = FALSE;
- g_main_context_iteration(g_main_context_default(), may_block);
-}
-
-void VolumeCatcherImpl::connected_okay()
-{
- pa_operation *op;
-
- // fetch global list of existing sinkinputs
- if ((op = llpa_context_get_sink_input_info_list(mPAContext,
- callback_discovered_sinkinput,
- this)))
- {
- llpa_operation_unref(op);
- }
-
- // subscribe to future global sinkinput changes
- llpa_context_set_subscribe_callback(mPAContext,
- callback_subscription_alert,
- this);
- if ((op = llpa_context_subscribe(mPAContext, (pa_subscription_mask_t)
- (PA_SUBSCRIPTION_MASK_SINK_INPUT),
- NULL, NULL)))
- {
- llpa_operation_unref(op);
- }
-}
-
-void VolumeCatcherImpl::update_all_volumes(F32 volume)
-{
- for (std::set<U32>::iterator it = mSinkInputIndices.begin();
- it != mSinkInputIndices.end(); ++it)
- {
- update_index_volume(*it, volume);
- }
-}
-
-void VolumeCatcherImpl::update_index_volume(U32 index, F32 volume)
-{
- static pa_cvolume cvol;
- llpa_cvolume_set(&cvol, mSinkInputNumChannels[index],
- llpa_sw_volume_from_linear(volume));
-
- pa_context *c = mPAContext;
- uint32_t idx = index;
- const pa_cvolume *cvolumep = &cvol;
- pa_context_success_cb_t cb = NULL; // okay as null
- void *userdata = NULL; // okay as null
-
- pa_operation *op;
- if ((op = llpa_context_set_sink_input_volume(c, idx, cvolumep, cb, userdata)))
- {
- llpa_operation_unref(op);
- }
-}
-
-
-void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *sii, int eol, void *userdata)
-{
- VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata);
- llassert(impl);
-
- if (0 == eol)
- {
- 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?
- {
- bool is_new = (impl->mSinkInputIndices.find(sii->index) ==
- impl->mSinkInputIndices.end());
-
- impl->mSinkInputIndices.insert(sii->index);
- impl->mSinkInputNumChannels[sii->index] = sii->channel_map.channels;
-
- if (is_new)
- {
- // new!
- impl->update_index_volume(sii->index, impl->mDesiredVolume);
- }
- else
- {
- // seen it already, do nothing.
- }
- }
- }
-}
-
-void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata)
-{
- VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata);
- llassert(impl);
-
- 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)))
- {
- llpa_operation_unref(op);
- }
- }
- else
- {
- // property change on this sinkinput - we don't care.
- }
- break;
-
- default:;
- }
-}
-
-void callback_context_state(pa_context *context, void *userdata)
-{
- VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata);
- llassert(impl);
-
- switch (llpa_context_get_state(context))
- {
- case PA_CONTEXT_READY:
- impl->mConnected = true;
- impl->connected_okay();
- break;
- case PA_CONTEXT_TERMINATED:
- impl->mConnected = false;
- break;
- case PA_CONTEXT_FAILED:
- impl->mConnected = false;
- break;
- default:;
- }
-}
-
-/////////////////////////////////////////////////////
-
-VolumeCatcher::VolumeCatcher()
-{
- pimpl = new VolumeCatcherImpl();
-}
-
-VolumeCatcher::~VolumeCatcher()
-{
- delete pimpl;
- pimpl = NULL;
-}
-
-void VolumeCatcher::setVolume(F32 volume)
-{
- llassert(pimpl);
- pimpl->setVolume(volume);
-}
-
-void VolumeCatcher::setPan(F32 pan)
-{
- // TODO: implement this (if possible)
-}
-
-void VolumeCatcher::pump()
-{
- llassert(pimpl);
- pimpl->pump();
-}
diff --git a/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc b/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc
deleted file mode 100755
index d806b48428..0000000000
--- a/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc
+++ /dev/null
@@ -1,21 +0,0 @@
-// required symbols to grab
-LL_PA_SYM(true, pa_context_connect, int, pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api);
-LL_PA_SYM(true, pa_context_disconnect, void, pa_context *c);
-LL_PA_SYM(true, pa_context_get_sink_input_info, pa_operation*, pa_context *c, uint32_t idx, pa_sink_input_info_cb_t cb, void *userdata);
-LL_PA_SYM(true, pa_context_get_sink_input_info_list, pa_operation*, pa_context *c, pa_sink_input_info_cb_t cb, void *userdata);
-LL_PA_SYM(true, pa_context_get_state, pa_context_state_t, pa_context *c);
-LL_PA_SYM(true, pa_context_new_with_proplist, pa_context*, pa_mainloop_api *mainloop, const char *name, pa_proplist *proplist);
-LL_PA_SYM(true, pa_context_set_sink_input_volume, pa_operation*, pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
-LL_PA_SYM(true, pa_context_set_state_callback, void, pa_context *c, pa_context_notify_cb_t cb, void *userdata);
-LL_PA_SYM(true, pa_context_set_subscribe_callback, void, pa_context *c, pa_context_subscribe_cb_t cb, void *userdata);
-LL_PA_SYM(true, pa_context_subscribe, pa_operation*, pa_context *c, pa_subscription_mask_t m, pa_context_success_cb_t cb, void *userdata);
-LL_PA_SYM(true, pa_context_unref, void, pa_context *c);
-LL_PA_SYM(true, pa_cvolume_set, pa_cvolume*, pa_cvolume *a, unsigned channels, pa_volume_t v);
-LL_PA_SYM(true, pa_operation_unref, void, pa_operation *o);
-LL_PA_SYM(true, pa_proplist_free, void, pa_proplist* p);
-LL_PA_SYM(true, pa_proplist_gets, const char*, pa_proplist *p, const char *key);
-LL_PA_SYM(true, pa_proplist_new, pa_proplist*, void);
-LL_PA_SYM(true, pa_proplist_sets, int, pa_proplist *p, const char *key, const char *value);
-LL_PA_SYM(true, pa_sw_volume_from_linear, pa_volume_t, double v);
-
-// optional symbols to grab
diff --git a/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc b/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc
deleted file mode 100755
index abf628c96c..0000000000
--- a/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc
+++ /dev/null
@@ -1,6 +0,0 @@
-// required symbols to grab
-LL_PA_SYM(true, pa_glib_mainloop_free, void, pa_glib_mainloop* g);
-LL_PA_SYM(true, pa_glib_mainloop_get_api, pa_mainloop_api*, pa_glib_mainloop* g);
-LL_PA_SYM(true, pa_glib_mainloop_new, pa_glib_mainloop *, GMainContext *c);
-
-// optional symbols to grab
diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp
deleted file mode 100755
index 3edeef51e3..0000000000
--- a/indra/media_plugins/webkit/media_plugin_webkit.cpp
+++ /dev/null
@@ -1,1481 +0,0 @@
-/**
- * @file media_plugin_webkit.cpp
- * @brief Webkit plugin for LLMedia API plugin system
- *
- * @cond
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- * @endcond
- */
-#include "llqtwebkit.h"
-#include "linden_common.h"
-#include "indra_constants.h" // for indra keyboard codes
-
-#include "lltimer.h"
-#include "llgl.h"
-
-#include "llplugininstance.h"
-#include "llpluginmessage.h"
-#include "llpluginmessageclasses.h"
-#include "media_plugin_base.h"
-
-// set to 1 if you're using the version of llqtwebkit that's QPixmap-ified
-#if LL_LINUX
-# define LL_QTWEBKIT_USES_PIXMAPS 0
-extern "C" {
-# include <glib.h>
-# include <glib-object.h>
-}
-#else
-# define LL_QTWEBKIT_USES_PIXMAPS 0
-#endif // LL_LINUX
-
-# include "volume_catcher.h"
-
-#if LL_WINDOWS
-# include <direct.h>
-#else
-# include <unistd.h>
-# include <stdlib.h>
-#endif
-
-#if LL_WINDOWS
- // *NOTE:Mani - This captures the module handle for the dll. This is used below
- // to get the path to this dll for webkit initialization.
- // I don't know how/if this can be done with apr...
- namespace { HMODULE gModuleHandle;};
- BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
- {
- gModuleHandle = (HMODULE) hinstDLL;
- return TRUE;
- }
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-//
-class MediaPluginWebKit :
- public MediaPluginBase,
- public LLEmbeddedBrowserWindowObserver
-{
-public:
- MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
- ~MediaPluginWebKit();
-
- /*virtual*/ void receiveMessage(const char *message_string);
-
-private:
-
- std::string mProfileDir;
- std::string mHostLanguage;
- std::string mUserAgent;
- bool mCookiesEnabled;
- bool mJavascriptEnabled;
- bool mPluginsEnabled;
- bool mEnableMediaPluginDebugging;
-
- enum
- {
- INIT_STATE_UNINITIALIZED, // LLQtWebkit hasn't been set up yet
- INIT_STATE_INITIALIZED, // LLQtWebkit has been set up, but no browser window has been created yet.
- INIT_STATE_NAVIGATING, // Browser instance has been set up and initial navigate to about:blank has been issued
- INIT_STATE_NAVIGATE_COMPLETE, // initial navigate to about:blank has completed
- INIT_STATE_WAIT_REDRAW, // First real navigate begin has been received, waiting for page changed event to start handling redraws
- INIT_STATE_WAIT_COMPLETE, // Waiting for first real navigate complete event
- INIT_STATE_RUNNING // All initialization gymnastics are complete.
- };
- int mBrowserWindowId;
- int mInitState;
- std::string mInitialNavigateURL;
- bool mNeedsUpdate;
-
- bool mCanCut;
- bool mCanCopy;
- bool mCanPaste;
- int mLastMouseX;
- int mLastMouseY;
- bool mFirstFocus;
- F32 mBackgroundR;
- F32 mBackgroundG;
- F32 mBackgroundB;
- std::string mTarget;
- LLTimer mElapsedTime;
-
- VolumeCatcher mVolumeCatcher;
-
- void postDebugMessage( const std::string& msg )
- {
- if ( mEnableMediaPluginDebugging )
- {
- std::stringstream str;
- str << "@Media Msg> " << "[" << (double)mElapsedTime.getElapsedTimeF32() << "] -- " << msg;
-
- LLPluginMessage debug_message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "debug_message");
- debug_message.setValue("message_text", str.str());
- debug_message.setValue("message_level", "info");
- sendMessage(debug_message);
- }
- }
-
- void setInitState(int state)
- {
-// std::cerr << "changing init state to " << state << std::endl;
- mInitState = state;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void update(int milliseconds)
- {
-#if LL_QTLINUX_DOESNT_HAVE_GLIB
- // pump glib generously, as Linux browser plugins are on the
- // glib main loop, even if the browser itself isn't - ugh
- // This is NOT NEEDED if Qt itself was built with glib
- // mainloop integration.
- GMainContext *mainc = g_main_context_default();
- while(g_main_context_iteration(mainc, FALSE));
-#endif // LL_QTLINUX_DOESNT_HAVE_GLIB
-
- // pump qt
- LLQtWebKit::getInstance()->pump( milliseconds );
-
- mVolumeCatcher.pump();
-
- checkEditState();
-
- if(mInitState == INIT_STATE_NAVIGATE_COMPLETE)
- {
- if(!mInitialNavigateURL.empty())
- {
- // We already have the initial navigate URL -- kick off the navigate.
- LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, mInitialNavigateURL );
- mInitialNavigateURL.clear();
- }
- }
-
- if ( (mInitState > INIT_STATE_WAIT_REDRAW) && mNeedsUpdate )
- {
- const unsigned char* browser_pixels = LLQtWebKit::getInstance()->grabBrowserWindow( mBrowserWindowId );
-
- unsigned int rowspan = LLQtWebKit::getInstance()->getBrowserRowSpan( mBrowserWindowId );
- unsigned int height = LLQtWebKit::getInstance()->getBrowserHeight( mBrowserWindowId );
-#if !LL_QTWEBKIT_USES_PIXMAPS
- unsigned int buffer_size = rowspan * height;
-#endif // !LL_QTWEBKIT_USES_PIXMAPS
-
-// std::cerr << "webkit plugin: updating" << std::endl;
-
- // TODO: should get rid of this memcpy if possible
- if ( mPixels && browser_pixels )
- {
-// std::cerr << " memcopy of " << buffer_size << " bytes" << std::endl;
-
-#if LL_QTWEBKIT_USES_PIXMAPS
- // copy the pixel data upside-down because of the co-ord system
- for (int y=0; y<height; ++y)
- {
- memcpy( &mPixels[(height-y-1)*rowspan], &browser_pixels[y*rowspan], rowspan );
- }
-#else
- memcpy( mPixels, browser_pixels, buffer_size );
-#endif // LL_QTWEBKIT_USES_PIXMAPS
- }
-
- if ( mWidth > 0 && mHeight > 0 )
- {
-// std::cerr << "Setting dirty, " << mWidth << " x " << mHeight << std::endl;
- setDirty( 0, 0, mWidth, mHeight );
- }
-
- mNeedsUpdate = false;
- };
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- bool initBrowser()
- {
- // already initialized
- if ( mInitState > INIT_STATE_UNINITIALIZED )
- return true;
-
- // set up directories
- char cwd[ FILENAME_MAX ]; // I *think* this is defined on all platforms we use
- if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
- {
- LL_WARNS() << "Couldn't get cwd - probably too long - failing to init." << LL_ENDL;
- return false;
- }
- std::string application_dir = std::string( cwd );
-
-#if LL_LINUX
- // take care to initialize glib properly, because some
- // versions of Qt don't, and we indirectly need it for (some
- // versions of) Flash to not crash the browser.
- if (!g_thread_supported ()) g_thread_init (NULL);
- g_type_init();
-#endif
-
-#if LL_DARWIN
- // When running under the Xcode debugger, there's a setting called "Break on Debugger()/DebugStr()" which defaults to being turned on.
- // This causes the environment variable USERBREAK to be set to 1, which causes these legacy calls to break into the debugger.
- // This wouldn't cause any problems except for the fact that the current release version of the Flash plugin has a call to Debugger() in it
- // which gets hit when the plugin is probed by webkit.
- // Unsetting the environment variable here works around this issue.
- unsetenv("USERBREAK");
-#endif
-
-#if LL_WINDOWS
- //*NOTE:Mani - On windows, at least, the component path is the
- // location of this dll's image file.
- std::string component_dir;
- char dll_path[_MAX_PATH];
- DWORD len = GetModuleFileNameA(gModuleHandle, (LPCH)&dll_path, _MAX_PATH);
- while(len && dll_path[ len ] != ('\\') )
- {
- len--;
- }
- if(len >= 0)
- {
- dll_path[len] = 0;
- component_dir = dll_path;
- }
- else
- {
- // *NOTE:Mani - This case should be an rare exception.
- // GetModuleFileNameA should always give you a full path, no?
- component_dir = application_dir;
- }
-#else
- std::string component_dir = application_dir;
-#endif
-
- // debug spam sent to viewer and displayed in the log as usual
- postDebugMessage( "Component dir set to: " + component_dir );
-
- // window handle - needed on Windows and must be app window.
-#if LL_WINDOWS
- char window_title[ MAX_PATH ];
- GetConsoleTitleA( window_title, MAX_PATH );
- void* native_window_handle = (void*)FindWindowA( NULL, window_title );
-#else
- void* native_window_handle = 0;
-#endif
-
- // main browser initialization
- bool result = LLQtWebKit::getInstance()->init( application_dir, component_dir, mProfileDir, native_window_handle );
- if ( result )
- {
- mInitState = INIT_STATE_INITIALIZED;
-
- // debug spam sent to viewer and displayed in the log as usual
- postDebugMessage( "browser initialized okay" );
-
- return true;
- };
-
- // debug spam sent to viewer and displayed in the log as usual
- postDebugMessage( "browser nOT initialized." );
-
- return false;
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- bool initBrowserWindow()
- {
- // already initialized
- if ( mInitState > INIT_STATE_INITIALIZED )
- return true;
-
- // not enough information to initialize the browser yet.
- if ( mWidth < 0 || mHeight < 0 || mDepth < 0 ||
- mTextureWidth < 0 || mTextureHeight < 0 )
- {
- return false;
- };
-
- // Set up host language before creating browser window
- if(!mHostLanguage.empty())
- {
- LLQtWebKit::getInstance()->setHostLanguage(mHostLanguage);
- postDebugMessage( "Setting language to " + mHostLanguage );
- }
-
- // turn on/off cookies based on what host app tells us
- LLQtWebKit::getInstance()->enableCookies( mCookiesEnabled );
-
- // turn on/off plugins based on what host app tells us
- LLQtWebKit::getInstance()->enablePlugins( mPluginsEnabled );
-
- // turn on/off Javascript based on what host app tells us
-#if LLQTWEBKIT_API_VERSION >= 11
- LLQtWebKit::getInstance()->enableJavaScript( mJavascriptEnabled );
-#else
- LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled );
-#endif
-
- std::stringstream str;
- str << "Cookies enabled = " << mCookiesEnabled << ", plugins enabled = " << mPluginsEnabled << ", Javascript enabled = " << mJavascriptEnabled;
- postDebugMessage( str.str() );
-
- // create single browser window
- mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight, mTarget);
-
- str.str("");
- str.clear();
- str << "Setting browser window size to " << mWidth << " x " << mHeight;
- postDebugMessage( str.str() );
-
- // tell LLQtWebKit about the size of the browser window
- LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight );
-
- // observer events that LLQtWebKit emits
- LLQtWebKit::getInstance()->addObserver( mBrowserWindowId, this );
-
- // append details to agent string
- LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent );
- postDebugMessage( "Updating user agent with " + mUserAgent );
-
-#if !LL_QTWEBKIT_USES_PIXMAPS
- // don't flip bitmap
- LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true );
-#endif // !LL_QTWEBKIT_USES_PIXMAPS
-
- // set background color
- // convert background color channels from [0.0, 1.0] to [0, 255];
- LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, int(mBackgroundR * 255.0f), int(mBackgroundG * 255.0f), int(mBackgroundB * 255.0f) );
-
- // Set state _before_ starting the navigate, since onNavigateBegin might get called before this call returns.
- setInitState(INIT_STATE_NAVIGATING);
-
- // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance.
- // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially
- // for the HTTP AUTH dialog issues (DEV-41731). Will fix at a later date.
- // Build a data URL like this: "data:text/html,%3Chtml%3E%3Cbody bgcolor=%22#RRGGBB%22%3E%3C/body%3E%3C/html%3E"
- // where RRGGBB is the background color in HTML style
- std::stringstream url;
-
- url << "data:text/html,%3Chtml%3E%3Cbody%20bgcolor=%22#";
- // convert background color channels from [0.0, 1.0] to [0, 255];
- url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundR * 255.0f);
- url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundG * 255.0f);
- url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundB * 255.0f);
- url << "%22%3E%3C/body%3E%3C/html%3E";
-
- //LL_DEBUGS() << "data url is: " << url.str() << LL_ENDL;
-
- // always display loading overlay now
-#if LLQTWEBKIT_API_VERSION >= 16
- LLQtWebKit::getInstance()->enableLoadingOverlay(mBrowserWindowId, true);
-#else
- LL_WARNS() << "Ignoring enableLoadingOverlay() call (llqtwebkit version is too old)." << LL_ENDL;
-#endif
- str.clear();
- str << "Loading overlay enabled = " << mEnableMediaPluginDebugging << " for mBrowserWindowId = " << mBrowserWindowId;
- postDebugMessage( str.str() );
-
- LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, url.str() );
-// LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" );
-
- return true;
- }
-
- void setVolume(F32 vol);
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- void onCursorChanged(const EventType& event)
- {
- LLQtWebKit::ECursor llqt_cursor = (LLQtWebKit::ECursor)event.getIntValue();
- std::string name;
-
- switch(llqt_cursor)
- {
- case LLQtWebKit::C_ARROW:
- name = "arrow";
- break;
- case LLQtWebKit::C_IBEAM:
- name = "ibeam";
- break;
- case LLQtWebKit::C_SPLITV:
- name = "splitv";
- break;
- case LLQtWebKit::C_SPLITH:
- name = "splith";
- break;
- case LLQtWebKit::C_POINTINGHAND:
- name = "hand";
- break;
-
- default:
- LL_WARNS() << "Unknown cursor ID: " << (int)llqt_cursor << LL_ENDL;
- break;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "cursor_changed");
- message.setValue("name", name);
- sendMessage(message);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- void onPageChanged( const EventType& event )
- {
- if(mInitState == INIT_STATE_WAIT_REDRAW)
- {
- setInitState(INIT_STATE_WAIT_COMPLETE);
- }
-
- // flag that an update is required
- mNeedsUpdate = true;
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- void onNavigateBegin(const EventType& event)
- {
- if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin");
- message.setValue("uri", event.getEventUri());
- message.setValueBoolean("history_back_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK));
- message.setValueBoolean("history_forward_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD));
- sendMessage(message);
-
- // debug spam sent to viewer and displayed in the log as usual
- postDebugMessage( "Navigate begin event at: " + event.getEventUri() );
-
- setStatus(STATUS_LOADING);
- }
-
- if(mInitState == INIT_STATE_NAVIGATE_COMPLETE)
- {
- // Skip the WAIT_REDRAW state now -- with the right background color set, it should no longer be necessary.
-// setInitState(INIT_STATE_WAIT_REDRAW);
- setInitState(INIT_STATE_WAIT_COMPLETE);
- }
-
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- void onNavigateComplete(const EventType& event)
- {
- if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
- {
- if(mInitState < INIT_STATE_RUNNING)
- {
- setInitState(INIT_STATE_RUNNING);
-
- // Clear the history, so the "back" button doesn't take you back to "about:blank".
- LLQtWebKit::getInstance()->clearHistory(mBrowserWindowId);
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete");
- message.setValue("uri", event.getEventUri());
- message.setValueS32("result_code", event.getIntValue());
- message.setValue("result_string", event.getStringValue());
- message.setValueBoolean("history_back_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK));
- message.setValueBoolean("history_forward_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD));
- sendMessage(message);
-
- setStatus(STATUS_LOADED);
- }
- else if(mInitState == INIT_STATE_NAVIGATING)
- {
- setInitState(INIT_STATE_NAVIGATE_COMPLETE);
- }
-
- // debug spam sent to viewer and displayed in the log as usual
- postDebugMessage( "Navigate complete event at: " + event.getEventUri() );
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- void onUpdateProgress(const EventType& event)
- {
- if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "progress");
- message.setValueS32("percent", event.getIntValue());
- sendMessage(message);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- void onStatusTextChange(const EventType& event)
- {
- if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "status_text");
- message.setValue("status", event.getStringValue());
- sendMessage(message);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- void onTitleChange(const EventType& event)
- {
- if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
- message.setValue("name", event.getStringValue());
- sendMessage(message);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- void onNavigateErrorPage(const EventType& event)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_error_page");
- message.setValueS32("status_code", event.getIntValue());
- sendMessage(message);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- void onLocationChange(const EventType& event)
- {
- if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed");
- message.setValue("uri", event.getEventUri());
- sendMessage(message);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- void onClickLinkHref(const EventType& event)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href");
- message.setValue("uri", event.getEventUri());
- message.setValue("target", event.getStringValue());
- message.setValue("uuid", event.getStringValue2());
- sendMessage(message);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- void onClickLinkNoFollow(const EventType& event)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow");
- message.setValue("uri", event.getEventUri());
-#if LLQTWEBKIT_API_VERSION >= 7
- message.setValue("nav_type", event.getNavigationType());
-#else
- message.setValue("nav_type", "clicked");
-#endif
- sendMessage(message);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- void onCookieChanged(const EventType& event)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "cookie_set");
- message.setValue("cookie", event.getStringValue());
- // These could be passed through as well, but aren't really needed.
-// message.setValue("uri", event.getEventUri());
-// message.setValueBoolean("dead", (event.getIntValue() != 0))
-
- // debug spam
- postDebugMessage( "Sending cookie_set message from plugin: " + event.getStringValue() );
-
- sendMessage(message);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- void onWindowCloseRequested(const EventType& event)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "close_request");
- message.setValue("uuid", event.getStringValue());
- sendMessage(message);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- void onWindowGeometryChangeRequested(const EventType& event)
- {
- int x, y, width, height;
- event.getRectValue(x, y, width, height);
-
- // This sometimes gets called with a zero-size request. Don't pass these along.
- if(width > 0 && height > 0)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "geometry_change");
- message.setValue("uuid", event.getStringValue());
- message.setValueS32("x", x);
- message.setValueS32("y", y);
- message.setValueS32("width", width);
- message.setValueS32("height", height);
- sendMessage(message);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- std::string onRequestFilePicker( const EventType& eventIn )
- {
- return blockingPickFile();
- }
-
- std::string mAuthUsername;
- std::string mAuthPassword;
- bool mAuthOK;
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- bool onAuthRequest(const std::string &in_url, const std::string &in_realm, std::string &out_username, std::string &out_password)
- {
- mAuthOK = false;
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_request");
- message.setValue("url", in_url);
- message.setValue("realm", in_realm);
- message.setValueBoolean("blocking_request", true);
-
- // The "blocking_request" key in the message means this sendMessage call will block until a response is received.
- sendMessage(message);
-
- if(mAuthOK)
- {
- out_username = mAuthUsername;
- out_password = mAuthPassword;
- }
-
- return mAuthOK;
- }
-
- void authResponse(LLPluginMessage &message)
- {
- mAuthOK = message.getValueBoolean("ok");
- if(mAuthOK)
- {
- mAuthUsername = message.getValue("username");
- mAuthPassword = message.getValue("password");
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // virtual
- void onLinkHovered(const EventType& event)
- {
- if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "link_hovered");
- message.setValue("link", event.getEventUri());
- message.setValue("title", event.getStringValue());
- message.setValue("text", event.getStringValue2());
- sendMessage(message);
- }
- }
-
- LLQtWebKit::EKeyboardModifier decodeModifiers(std::string &modifiers)
- {
- int result = 0;
-
- if(modifiers.find("shift") != std::string::npos)
- result |= LLQtWebKit::KM_MODIFIER_SHIFT;
-
- if(modifiers.find("alt") != std::string::npos)
- result |= LLQtWebKit::KM_MODIFIER_ALT;
-
- if(modifiers.find("control") != std::string::npos)
- result |= LLQtWebKit::KM_MODIFIER_CONTROL;
-
- if(modifiers.find("meta") != std::string::npos)
- result |= LLQtWebKit::KM_MODIFIER_META;
-
- return (LLQtWebKit::EKeyboardModifier)result;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void deserializeKeyboardData( LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers )
- {
- native_scan_code = 0;
- native_virtual_key = 0;
- native_modifiers = 0;
-
- if( native_key_data.isMap() )
- {
-#if LL_DARWIN
- native_scan_code = (uint32_t)(native_key_data["char_code"].asInteger());
- native_virtual_key = (uint32_t)(native_key_data["key_code"].asInteger());
- native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger());
-#elif LL_WINDOWS
- native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger());
- native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger());
- // TODO: I don't think we need to do anything with native modifiers here -- please verify
-#elif LL_LINUX
- native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger());
- native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger());
- native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger());
-#else
- // Add other platforms here as needed
-#endif
- };
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void keyEvent(LLQtWebKit::EKeyEvent key_event, int key, LLQtWebKit::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap())
- {
- // The incoming values for 'key' will be the ones from indra_constants.h
- std::string utf8_text;
-
- if(key < KEY_SPECIAL)
- {
- // Low-ascii characters need to get passed through.
- utf8_text = (char)key;
- }
-
- // Any special-case handling we want to do for particular keys...
- switch((KEY)key)
- {
- // ASCII codes for some standard keys
- case LLQtWebKit::KEY_BACKSPACE: utf8_text = (char)8; break;
- case LLQtWebKit::KEY_TAB: utf8_text = (char)9; break;
- case LLQtWebKit::KEY_RETURN: utf8_text = (char)13; break;
- case LLQtWebKit::KEY_PAD_RETURN: utf8_text = (char)13; break;
- case LLQtWebKit::KEY_ESCAPE: utf8_text = (char)27; break;
-
- default:
- break;
- }
-
-// std::cerr << "key event " << (int)key_event << ", native_key_data = " << native_key_data << std::endl;
-
- uint32_t native_scan_code = 0;
- uint32_t native_virtual_key = 0;
- uint32_t native_modifiers = 0;
- deserializeKeyboardData( native_key_data, native_scan_code, native_virtual_key, native_modifiers );
-
- LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers);
-
- checkEditState();
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void unicodeInput( const std::string &utf8str, LLQtWebKit::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap())
- {
- uint32_t key = LLQtWebKit::KEY_NONE;
-
-// std::cerr << "unicode input, native_key_data = " << native_key_data << std::endl;
-
- if(utf8str.size() == 1)
- {
- // The only way a utf8 string can be one byte long is if it's actually a single 7-bit ascii character.
- // In this case, use it as the key value.
- key = utf8str[0];
- }
-
- uint32_t native_scan_code = 0;
- uint32_t native_virtual_key = 0;
- uint32_t native_modifiers = 0;
- deserializeKeyboardData( native_key_data, native_scan_code, native_virtual_key, native_modifiers );
-
- LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_DOWN, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers);
- LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_UP, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers);
-
- checkEditState();
- };
-
- void checkEditState(void)
- {
- bool can_cut = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_CUT);
- bool can_copy = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_COPY);
- bool can_paste = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_PASTE);
-
- if((can_cut != mCanCut) || (can_copy != mCanCopy) || (can_paste != mCanPaste))
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_state");
-
- if(can_cut != mCanCut)
- {
- mCanCut = can_cut;
- message.setValueBoolean("cut", can_cut);
- }
-
- if(can_copy != mCanCopy)
- {
- mCanCopy = can_copy;
- message.setValueBoolean("copy", can_copy);
- }
-
- if(can_paste != mCanPaste)
- {
- mCanPaste = can_paste;
- message.setValueBoolean("paste", can_paste);
- }
-
- sendMessage(message);
-
- }
- }
-
- std::string mPickedFile;
-
- std::string blockingPickFile(void)
- {
- mPickedFile.clear();
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file");
- message.setValueBoolean("blocking_request", true);
-
- // The "blocking_request" key in the message means this sendMessage call will block until a response is received.
- sendMessage(message);
-
- return mPickedFile;
- }
-
- void onPickFileResponse(const std::string &file)
- {
- mPickedFile = file;
- }
-
-};
-
-MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) :
- MediaPluginBase(host_send_func, host_user_data)
-{
-// std::cerr << "MediaPluginWebKit constructor" << std::endl;
-
- mBrowserWindowId = 0;
- mInitState = INIT_STATE_UNINITIALIZED;
- mNeedsUpdate = true;
- mCanCut = false;
- mCanCopy = false;
- mCanPaste = false;
- mLastMouseX = 0;
- mLastMouseY = 0;
- mFirstFocus = true;
- mBackgroundR = 0.0f;
- mBackgroundG = 0.0f;
- mBackgroundB = 0.0f;
-
- mHostLanguage = "en"; // default to english
- mJavascriptEnabled = true; // default to on
- mPluginsEnabled = true; // default to on
- mEnableMediaPluginDebugging = false;
- mUserAgent = "LLPluginMedia Web Browser";
-
- mElapsedTime.reset();
-}
-
-MediaPluginWebKit::~MediaPluginWebKit()
-{
- // unhook observer
- LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this );
-
- // clean up
- LLQtWebKit::getInstance()->reset();
-
-// std::cerr << "MediaPluginWebKit destructor" << std::endl;
-}
-
-void MediaPluginWebKit::receiveMessage(const char *message_string)
-{
-// std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl;
- LLPluginMessage message_in;
-
- if(message_in.parse(message_string) >= 0)
- {
- std::string message_class = message_in.getClass();
- std::string message_name = message_in.getName();
- if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
- {
- if(message_name == "init")
- {
- LLPluginMessage message("base", "init_response");
- LLSD versions = LLSD::emptyMap();
- versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
- versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
- versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION;
- message.setValueLLSD("versions", versions);
-
- std::string plugin_version = "Webkit media plugin, Webkit version ";
- plugin_version += LLQtWebKit::getInstance()->getVersion();
- message.setValue("plugin_version", plugin_version);
- sendMessage(message);
- }
- else if(message_name == "idle")
- {
- // no response is necessary here.
- F64 time = message_in.getValueReal("time");
-
- // Convert time to milliseconds for update()
- update((int)(time * 1000.0f));
- }
- else if(message_name == "cleanup")
- {
- // DTOR most likely won't be called but the recent change to the way this process
- // is (not) killed means we see this message and can do what we need to here.
- // Note: this cleanup is ultimately what writes cookies to the disk
- LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this );
- LLQtWebKit::getInstance()->reset();
- }
- else if(message_name == "shm_added")
- {
- SharedSegmentInfo info;
- info.mAddress = message_in.getValuePointer("address");
- info.mSize = (size_t)message_in.getValueS32("size");
- std::string name = message_in.getValue("name");
-
-// std::cerr << "MediaPluginWebKit::receiveMessage: shared memory added, name: " << name
-// << ", size: " << info.mSize
-// << ", address: " << info.mAddress
-// << std::endl;
-
- mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
-
- }
- else if(message_name == "shm_remove")
- {
- std::string name = message_in.getValue("name");
-
-// std::cerr << "MediaPluginWebKit::receiveMessage: shared memory remove, name = " << name << std::endl;
-
- SharedSegmentMap::iterator iter = mSharedSegments.find(name);
- if(iter != mSharedSegments.end())
- {
- if(mPixels == iter->second.mAddress)
- {
- // This is the currently active pixel buffer. Make sure we stop drawing to it.
- mPixels = NULL;
- mTextureSegmentName.clear();
- }
- mSharedSegments.erase(iter);
- }
- else
- {
-// std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl;
- }
-
- // Send the response so it can be cleaned up.
- LLPluginMessage message("base", "shm_remove_response");
- message.setValue("name", name);
- sendMessage(message);
- }
- else
- {
-// std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl;
- }
- }
- else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
- {
- if(message_name == "set_volume")
- {
- F32 volume = (F32)message_in.getValueReal("volume");
- setVolume(volume);
- }
- }
- else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
- {
- if(message_name == "init")
- {
- mTarget = message_in.getValue("target");
-
- // This is the media init message -- all necessary data for initialization should have been received.
- if(initBrowser())
- {
-
- // Plugin gets to decide the texture parameters to use.
- mDepth = 4;
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
- message.setValueS32("default_width", 1024);
- message.setValueS32("default_height", 1024);
- message.setValueS32("depth", mDepth);
- message.setValueU32("internalformat", GL_RGBA);
- #if LL_QTWEBKIT_USES_PIXMAPS
- message.setValueU32("format", GL_BGRA_EXT); // I hope this isn't system-dependant... is it? If so, we'll have to check the root window's pixel layout or something... yuck.
- #else
- message.setValueU32("format", GL_RGBA);
- #endif // LL_QTWEBKIT_USES_PIXMAPS
- message.setValueU32("type", GL_UNSIGNED_BYTE);
- message.setValueBoolean("coords_opengl", true);
- sendMessage(message);
- }
- else
- {
- // if initialization failed, we're done.
- mDeleteMe = true;
- }
-
- }
- else if(message_name == "set_user_data_path")
- {
- std::string user_data_path = message_in.getValue("path"); // n.b. always has trailing platform-specific dir-delimiter
- mProfileDir = user_data_path + "browser_profile";
-
- // FIXME: Should we do anything with this if it comes in after the browser has been initialized?
- }
- else if(message_name == "set_language_code")
- {
- mHostLanguage = message_in.getValue("language");
-
- // FIXME: Should we do anything with this if it comes in after the browser has been initialized?
- }
- else if(message_name == "plugins_enabled")
- {
- mPluginsEnabled = message_in.getValueBoolean("enable");
- }
- else if(message_name == "javascript_enabled")
- {
- mJavascriptEnabled = message_in.getValueBoolean("enable");
- }
- 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");
- mBackgroundR = (F32)message_in.getValueReal("background_r");
- mBackgroundG = (F32)message_in.getValueReal("background_g");
- mBackgroundB = (F32)message_in.getValueReal("background_b");
-// mBackgroundA = message_in.setValueReal("background_a"); // Ignore any alpha
-
- if(!name.empty())
- {
- // Find the shared memory region with this name
- SharedSegmentMap::iterator iter = mSharedSegments.find(name);
- if(iter != mSharedSegments.end())
- {
- mPixels = (unsigned char*)iter->second.mAddress;
- mWidth = width;
- mHeight = height;
-
- if(initBrowserWindow())
- {
-
- // size changed so tell the browser
- LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight );
-
- // std::cerr << "webkit plugin: set size to " << mWidth << " x " << mHeight
- // << ", rowspan is " << LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) << std::endl;
-
- S32 real_width = LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) / LLQtWebKit::getInstance()->getBrowserDepth(mBrowserWindowId);
-
- // The actual width the browser will be drawing to is probably smaller... let the host know by modifying texture_width in the response.
- if(real_width <= texture_width)
- {
- texture_width = real_width;
- }
- else
- {
- // This won't work -- it'll be bigger than the allocated memory. This is a fatal error.
- // std::cerr << "Fatal error: browser rowbytes greater than texture width" << std::endl;
- mDeleteMe = true;
- return;
- }
- }
- else
- {
- // Setting up the browser window failed. This is a fatal error.
- mDeleteMe = true;
- }
-
-
- mTextureWidth = texture_width;
- mTextureHeight = 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);
-
- }
- else if(message_name == "load_uri")
- {
- std::string uri = message_in.getValue("uri");
-
-// std::cout << "loading URI: " << uri << std::endl;
-
- if(!uri.empty())
- {
- if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
- {
- LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, uri );
- }
- else
- {
- mInitialNavigateURL = uri;
- }
- }
- }
- else if(message_name == "mouse_event")
- {
- std::string event = message_in.getValue("event");
- S32 button = message_in.getValueS32("button");
- mLastMouseX = message_in.getValueS32("x");
- mLastMouseY = message_in.getValueS32("y");
- std::string modifiers = message_in.getValue("modifiers");
-
- // Treat unknown mouse events as mouse-moves.
- LLQtWebKit::EMouseEvent mouse_event = LLQtWebKit::ME_MOUSE_MOVE;
- if(event == "down")
- {
- mouse_event = LLQtWebKit::ME_MOUSE_DOWN;
- }
- else if(event == "up")
- {
- mouse_event = LLQtWebKit::ME_MOUSE_UP;
- }
- else if(event == "double_click")
- {
- mouse_event = LLQtWebKit::ME_MOUSE_DOUBLE_CLICK;
- }
-
- LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId, mouse_event, button, mLastMouseX, mLastMouseY, decodeModifiers(modifiers));
- checkEditState();
- }
- else if(message_name == "scroll_event")
- {
- S32 x = message_in.getValueS32("x");
- S32 y = message_in.getValueS32("y");
- std::string modifiers = message_in.getValue("modifiers");
-
- // Incoming scroll events are adjusted so that 1 detent is approximately 1 unit.
- // Qt expects 1 detent to be 120 units.
- // It also seems that our y scroll direction is inverted vs. what Qt expects.
-
- x *= 120;
- y *= -120;
-
- LLQtWebKit::getInstance()->scrollWheelEvent(mBrowserWindowId, mLastMouseX, mLastMouseY, x, y, decodeModifiers(modifiers));
- }
- else if(message_name == "key_event")
- {
- std::string event = message_in.getValue("event");
- S32 key = message_in.getValueS32("key");
- std::string modifiers = message_in.getValue("modifiers");
- LLSD native_key_data = message_in.getValueLLSD("native_key_data");
-
- // Treat unknown events as key-up for safety.
- LLQtWebKit::EKeyEvent key_event = LLQtWebKit::KE_KEY_UP;
- if(event == "down")
- {
- key_event = LLQtWebKit::KE_KEY_DOWN;
- }
- else if(event == "repeat")
- {
- key_event = LLQtWebKit::KE_KEY_REPEAT;
- }
-
- keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data);
- }
- else if(message_name == "text_event")
- {
- std::string text = message_in.getValue("text");
- std::string modifiers = message_in.getValue("modifiers");
- LLSD native_key_data = message_in.getValueLLSD("native_key_data");
-
- unicodeInput(text, decodeModifiers(modifiers), native_key_data);
- }
- if(message_name == "edit_cut")
- {
- LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_CUT );
- checkEditState();
- }
- if(message_name == "edit_copy")
- {
- LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_COPY );
- checkEditState();
- }
- if(message_name == "edit_paste")
- {
- LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_PASTE );
- checkEditState();
- }
- if(message_name == "pick_file_response")
- {
- onPickFileResponse(message_in.getValue("file"));
- }
- if(message_name == "auth_response")
- {
- authResponse(message_in);
- }
- else
- if(message_name == "enable_media_plugin_debugging")
- {
- mEnableMediaPluginDebugging = message_in.getValueBoolean( "enable" );
- }
- else
- if(message_name == "js_enable_object")
- {
-#if LLQTWEBKIT_API_VERSION >= 9
- bool enable = message_in.getValueBoolean( "enable" );
- LLQtWebKit::getInstance()->setSLObjectEnabled( enable );
-#endif
- }
- else
- if(message_name == "js_agent_location")
- {
-#if LLQTWEBKIT_API_VERSION >= 9
- F32 x = (F32)message_in.getValueReal("x");
- F32 y = (F32)message_in.getValueReal("y");
- F32 z = (F32)message_in.getValueReal("z");
- LLQtWebKit::getInstance()->setAgentLocation( x, y, z );
- LLQtWebKit::getInstance()->emitLocation();
-#endif
- }
- else
- if(message_name == "js_agent_global_location")
- {
-#if LLQTWEBKIT_API_VERSION >= 9
- F32 x = (F32)message_in.getValueReal("x");
- F32 y = (F32)message_in.getValueReal("y");
- F32 z = (F32)message_in.getValueReal("z");
- LLQtWebKit::getInstance()->setAgentGlobalLocation( x, y, z );
- LLQtWebKit::getInstance()->emitLocation();
-#endif
- }
- else
- if(message_name == "js_agent_orientation")
- {
-#if LLQTWEBKIT_API_VERSION >= 9
- F32 angle = (F32)message_in.getValueReal("angle");
- LLQtWebKit::getInstance()->setAgentOrientation( angle );
- LLQtWebKit::getInstance()->emitLocation();
-#endif
- }
- else
- if(message_name == "js_agent_region")
- {
-#if LLQTWEBKIT_API_VERSION >= 9
- const std::string& region = message_in.getValue("region");
- LLQtWebKit::getInstance()->setAgentRegion( region );
- LLQtWebKit::getInstance()->emitLocation();
-#endif
- }
- else
- if(message_name == "js_agent_maturity")
- {
-#if LLQTWEBKIT_API_VERSION >= 9
- const std::string& maturity = message_in.getValue("maturity");
- LLQtWebKit::getInstance()->setAgentMaturity( maturity );
- LLQtWebKit::getInstance()->emitMaturity();
-#endif
- }
- else
- if(message_name == "js_agent_language")
- {
-#if LLQTWEBKIT_API_VERSION >= 9
- const std::string& language = message_in.getValue("language");
- LLQtWebKit::getInstance()->setAgentLanguage( language );
- LLQtWebKit::getInstance()->emitLanguage();
-#endif
- }
- else
- {
-// std::cerr << "MediaPluginWebKit::receiveMessage: unknown media message: " << message_string << std::endl;
- }
- }
- else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
- {
- if(message_name == "focus")
- {
- bool val = message_in.getValueBoolean("focused");
- LLQtWebKit::getInstance()->focusBrowser( mBrowserWindowId, val );
-
- if(mFirstFocus && val)
- {
- // On the first focus, post a tab key event. This fixes a problem with initial focus.
- std::string empty;
- keyEvent(LLQtWebKit::KE_KEY_DOWN, KEY_TAB, decodeModifiers(empty));
- keyEvent(LLQtWebKit::KE_KEY_UP, KEY_TAB, decodeModifiers(empty));
- mFirstFocus = false;
- }
- }
- else if(message_name == "set_page_zoom_factor")
- {
-#if LLQTWEBKIT_API_VERSION >= 15
- F32 factor = (F32)message_in.getValueReal("factor");
- LLQtWebKit::getInstance()->setPageZoomFactor(factor);
-#else
- LL_WARNS() << "Ignoring setPageZoomFactor message (llqtwebkit version is too old)." << LL_ENDL;
-#endif
- }
- else if(message_name == "clear_cache")
- {
- LLQtWebKit::getInstance()->clearCache();
- }
- else if(message_name == "clear_cookies")
- {
- LLQtWebKit::getInstance()->clearAllCookies();
- }
- else if(message_name == "enable_cookies")
- {
- mCookiesEnabled = message_in.getValueBoolean("enable");
- LLQtWebKit::getInstance()->enableCookies( mCookiesEnabled );
- }
- else if(message_name == "enable_plugins")
- {
- mPluginsEnabled = message_in.getValueBoolean("enable");
- LLQtWebKit::getInstance()->enablePlugins( mPluginsEnabled );
- }
- else if(message_name == "enable_javascript")
- {
- mJavascriptEnabled = message_in.getValueBoolean("enable");
- //LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled );
- }
- else if(message_name == "set_cookies")
- {
- LLQtWebKit::getInstance()->setCookies(message_in.getValue("cookies"));
-
- // debug spam
- postDebugMessage( "Plugin setting cookie: " + message_in.getValue("cookies") );
- }
- else if(message_name == "proxy_setup")
- {
- bool val = message_in.getValueBoolean("enable");
- std::string host = message_in.getValue("host");
- int port = message_in.getValueS32("port");
- LLQtWebKit::getInstance()->enableProxy( val, host, port );
- }
- else if(message_name == "browse_stop")
- {
- LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_STOP );
- }
- else if(message_name == "browse_reload")
- {
- // foo = message_in.getValueBoolean("ignore_cache");
- LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_RELOAD );
- }
- else if(message_name == "browse_forward")
- {
- LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD );
- }
- else if(message_name == "browse_back")
- {
- LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK );
- }
- else if(message_name == "set_status_redirect")
- {
- int code = message_in.getValueS32("code");
- std::string url = message_in.getValue("url");
- if ( 404 == code ) // browser lib only supports 404 right now
- {
-#if LLQTWEBKIT_API_VERSION < 8
- LLQtWebKit::getInstance()->set404RedirectUrl( mBrowserWindowId, url );
-#endif
- };
- }
- else if(message_name == "set_user_agent")
- {
- mUserAgent = message_in.getValue("user_agent");
- LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent );
- }
- else if(message_name == "show_web_inspector")
- {
-#if LLQTWEBKIT_API_VERSION >= 10
- bool val = message_in.getValueBoolean("show");
- LLQtWebKit::getInstance()->showWebInspector( val );
-#else
- LL_WARNS() << "Ignoring showWebInspector message (llqtwebkit version is too old)." << LL_ENDL;
-#endif
- }
- else if(message_name == "ignore_ssl_cert_errors")
- {
-#if LLQTWEBKIT_API_VERSION >= 3
- LLQtWebKit::getInstance()->setIgnoreSSLCertErrors( message_in.getValueBoolean("ignore") );
-#else
- LL_WARNS() << "Ignoring ignore_ssl_cert_errors message (llqtwebkit version is too old)." << LL_ENDL;
-#endif
- }
- else if(message_name == "add_certificate_file_path")
- {
-#if LLQTWEBKIT_API_VERSION >= 6
- LLQtWebKit::getInstance()->setCAFile( message_in.getValue("path") );
-#else
- LL_WARNS() << "Ignoring add_certificate_file_path message (llqtwebkit version is too old)." << LL_ENDL;
-#endif
- }
- else if(message_name == "init_history")
- {
- // Initialize browser history
- LLSD history = message_in.getValueLLSD("history");
- // First, clear the URL history
- LLQtWebKit::getInstance()->clearHistory(mBrowserWindowId);
- // Then, add the history items in order
- LLSD::array_iterator iter_history = history.beginArray();
- LLSD::array_iterator end_history = history.endArray();
- for(; iter_history != end_history; ++iter_history)
- {
- std::string url = (*iter_history).asString();
- if(! url.empty()) {
- LLQtWebKit::getInstance()->prependHistoryUrl(mBrowserWindowId, url);
- }
- }
- }
- else if(message_name == "proxy_window_opened")
- {
- std::string target = message_in.getValue("target");
- std::string uuid = message_in.getValue("uuid");
- LLQtWebKit::getInstance()->proxyWindowOpened(mBrowserWindowId, target, uuid);
- }
- else if(message_name == "proxy_window_closed")
- {
- std::string uuid = message_in.getValue("uuid");
- LLQtWebKit::getInstance()->proxyWindowClosed(mBrowserWindowId, uuid);
- }
- else
- {
-// std::cerr << "MediaPluginWebKit::receiveMessage: unknown media_browser message: " << message_string << std::endl;
- };
- }
- else
- {
-// std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl;
- };
- }
-}
-
-void MediaPluginWebKit::setVolume(F32 volume)
-{
- mVolumeCatcher.setVolume(volume);
-}
-
-int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
-{
- MediaPluginWebKit *self = new MediaPluginWebKit(host_send_func, host_user_data);
- *plugin_send_func = MediaPluginWebKit::staticReceiveMessage;
- *plugin_user_data = (void*)self;
-
- return 0;
-}
-
-
diff --git a/indra/media_plugins/winmmshim/CMakeLists.txt b/indra/media_plugins/winmmshim/CMakeLists.txt
index bf74f81809..6890589892 100755
--- a/indra/media_plugins/winmmshim/CMakeLists.txt
+++ b/indra/media_plugins/winmmshim/CMakeLists.txt
@@ -22,9 +22,6 @@ set(winmm_shim_HEADER_FILES
list(APPEND winmm_shim_SOURCE_FILES ${winmm_shim_HEADER_FILES})
-set_source_files_properties(${media_plugin_webkit_HEADER_FILES}
- PROPERTIES HEADER_FILE_ONLY TRUE)
-
add_library(winmm_shim
SHARED
${winmm_shim_SOURCE_FILES}
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index feb2e207fe..51efd76484 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -44,7 +44,6 @@ include(OPENAL)
include(OpenGL)
include(OpenSSL)
include(PNG)
-include(Prebuilt)
include(TemplateCheck)
include(UI)
include(UnixInstall)
@@ -62,9 +61,6 @@ if(FMODEX)
include_directories(${FMODEX_INCLUDE_DIR})
endif(FMODEX)
-# install SLPlugin host executable and its dynamic-library plugins
-use_prebuilt_binary(slplugins)
-
include_directories(
${DBUSGLIB_INCLUDE_DIRS}
${JSONCPP_INCLUDE_DIR}
@@ -1749,44 +1745,12 @@ if (WINDOWS)
${CMAKE_CURRENT_SOURCE_DIR}/featuretable.txt
${CMAKE_CURRENT_SOURCE_DIR}/featuretable_xp.txt
${ARCH_PREBUILT_DIRS_RELEASE}/libeay32.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/qtcore4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/qtgui4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/qtnetwork4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/qtopengl4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/qtwebkit4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/qtxmlpatterns4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/ssleay32.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qgif4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qico4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qjpeg4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qmng4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qsvg4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qtiff4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qcncodecs4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qjpcodecs4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qkrcodecs4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qtwcodecs4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/libeay32.dll
- ${ARCH_PREBUILT_DIRS_DEBUG}/qtcored4.dll
- ${ARCH_PREBUILT_DIRS_DEBUG}/qtguid4.dll
- ${ARCH_PREBUILT_DIRS_DEBUG}/qtnetworkd4.dll
- ${ARCH_PREBUILT_DIRS_DEBUG}/qtopengld4.dll
- ${ARCH_PREBUILT_DIRS_DEBUG}/qtwebkitd4.dll
- ${ARCH_PREBUILT_DIRS_DEBUG}/qtxmlpatternsd4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/ssleay32.dll
- ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qgifd4.dll
- ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qicod4.dll
- ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qjpegd4.dll
- ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qmngd4.dll
- ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qsvgd4.dll
- ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qtiffd4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qcncodecsd4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qjpcodecsd4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qkrcodecsd4.dll
- ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qtwcodecsd4.dll
SLPlugin
media_plugin_quicktime
- media_plugin_webkit
+ media_plugin_cef
winmm_shim
windows-crash-logger
)
@@ -1831,10 +1795,10 @@ if (WINDOWS)
add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts)
endif (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
-## add_dependencies(${VIEWER_BINARY_NAME}
-## SLPlugin
-## windows-crash-logger
-## )
+ add_dependencies(${VIEWER_BINARY_NAME}
+ SLPlugin
+ windows-crash-logger
+ )
# sets the 'working directory' for debugging from visual studio.
if (NOT UNATTENDED)
@@ -2001,9 +1965,8 @@ if (LINUX)
set(COPY_INPUT_DEPENDENCIES
${VIEWER_BINARY_NAME}
linux-crash-logger
-## SLPlugin
-## media_plugin_webkit
-## media_plugin_gstreamer010
+ SLPlugin
+ media_plugin_gstreamer010
llcommon
)
@@ -2115,7 +2078,7 @@ if (DARWIN)
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
)
-##add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit mac-crash-logger)
+ add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_cef mac-crash-logger)
add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger)
if (ENABLE_SIGNING)
@@ -2170,20 +2133,19 @@ if (PACKAGE)
if (DARWIN)
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
# *TODO: Generate these search dirs in the cmake files related to each binary.
-## list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/llplugin/slplugin/${CMAKE_CFG_INTDIR}")
+ list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/llplugin/slplugin/${CMAKE_CFG_INTDIR}")
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/mac_crash_logger/${CMAKE_CFG_INTDIR}")
-## list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/gstreamer010/${CMAKE_CFG_INTDIR}")
-## list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/quicktime/${CMAKE_CFG_INTDIR}")
-## list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/webkit/${CMAKE_CFG_INTDIR}")
+ list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/gstreamer010/${CMAKE_CFG_INTDIR}")
+ list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/quicktime/${CMAKE_CFG_INTDIR}")
set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-darwin.tar.bz2")
-## set(VIEWER_EXE_GLOBS "'Second Life' SLPlugin mac-crash-logger")
+ set(VIEWER_EXE_GLOBS "'Second Life' SLPlugin mac-crash-logger")
set(VIEWER_EXE_GLOBS "'Second Life' mac-crash-logger")
set(VIEWER_LIB_GLOB "*.dylib")
endif (DARWIN)
if (LINUX)
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/packaged")
set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-linux.tar.bz2")
-## set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin")
+ set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin")
set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin")
set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*")
set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest)
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 4351a7e3a3..1454f6ed4b 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-3.8.7
+4.0.1
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 2ca090b179..d5549013fa 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -734,7 +734,7 @@
<string>F32</string>
<key>Value</key>
<integer>60</integer>
- </map>
+ </map>
<key>AvatarRotateThresholdFast</key>
<map>
<key>Comment</key>
@@ -745,7 +745,7 @@
<string>F32</string>
<key>Value</key>
<integer>2</integer>
- </map>
+ </map>
<key>AvatarBakedTextureUploadTimeout</key>
<map>
<key>Comment</key>
@@ -1339,7 +1339,7 @@
<string>String</string>
<key>Value</key>
<string />
- </map>
+ </map>
<key>CacheNumberOfRegionsForObjects</key>
<map>
<key>Comment</key>
@@ -3799,7 +3799,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
- </map>
+ </map>
<key>FirstSelectedEnabledPopups</key>
<map>
<key>Comment</key>
@@ -3810,7 +3810,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
- </map>
+ </map>
<key>FixedWeather</key>
<map>
<key>Comment</key>
@@ -3932,7 +3932,7 @@
<key>Value</key>
<string>SW</string>
</map>
-
+
<key>FloaterStatisticsRect</key>
<map>
<key>Comment</key>
@@ -4459,7 +4459,7 @@
<string>String</string>
<key>Value</key>
<string>http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/howto/index.html</string>
- </map>
+ </map>
<key>HomeSidePanelURL</key>
<map>
<key>Comment</key>
@@ -4525,7 +4525,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
- </map>
+ </map>
<key>HostID</key>
<map>
<key>Comment</key>
@@ -4613,7 +4613,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
- </map>
+ </map>
<key>IgnorePixelDepth</key>
<map>
<key>Comment</key>
@@ -4668,7 +4668,7 @@
<string>F32</string>
<key>Value</key>
<real>0.5</real>
- </map>
+ </map>
<key>InspectorShowTime</key>
<map>
<key>Comment</key>
@@ -4679,7 +4679,7 @@
<string>F32</string>
<key>Value</key>
<real>3.0</real>
- </map>
+ </map>
<key>InstallLanguage</key>
<map>
<key>Comment</key>
@@ -5241,7 +5241,7 @@
<key>Value</key>
<string>0.0.0</string>
</map>
-
+
<key>LastSnapshotToProfileHeight</key>
<map>
<key>Comment</key>
@@ -6320,7 +6320,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
- </map>
+ </map>
<key>MenuAccessKeyTime</key>
<map>
<key>Comment</key>
@@ -6485,7 +6485,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
- </map>
+ </map>
<key>MouseSun</key>
<map>
<key>Comment</key>
@@ -6650,7 +6650,7 @@
<string>String</string>
<key>Value</key>
<string />
- </map>
+ </map>
<key>NextLoginLocation</key>
<map>
<key>Comment</key>
@@ -6774,7 +6774,7 @@
<string>String</string>
<key>Value</key>
<string>toast</string>
- </map>
+ </map>
<key>NotificationFriendIMOptions</key>
<map>
<key>Comment</key>
@@ -6830,7 +6830,7 @@
<string>String</string>
<key>Value</key>
<string>toast</string>
- </map>
+ </map>
<key>NotificationObjectIMOptions</key>
<map>
<key>Comment</key>
@@ -6844,7 +6844,7 @@
<string>String</string>
<key>Value</key>
<string>toast</string>
- </map>
+ </map>
<key>NotificationToastLifeTime</key>
<map>
<key>Comment</key>
@@ -7403,7 +7403,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
- </map>
+ </map>
<key>PlaySoundFriendIM</key>
<map>
<key>Comment</key>
@@ -7514,7 +7514,7 @@
<key>Value</key>
<real>0.9</real>
</map>
-
+
<key>PlainTextChatHistory</key>
<map>
<key>Comment</key>
@@ -7526,7 +7526,7 @@
<key>Value</key>
<integer>0</integer>
</map>
-
+
<key>PluginInstancesLow</key>
<map>
<key>Comment</key>
@@ -7780,7 +7780,7 @@
<real>0.4</real>
</array>
</map>
-
+
<key>PreviewDirection2</key>
<map>
<key>Comment</key>
@@ -8092,7 +8092,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <real>5.0</real>
+ <real>10.0</real>
</map>
<key>MediaRollOffMax</key>
<map>
@@ -8390,7 +8390,7 @@
<key>RenderComplexityStaticMax</key>
<map>
<key>Comment</key>
- <string>Sets a static max value for scaling of RenderComplexity
+ <string>Sets a static max value for scaling of RenderComplexity
display (-1 for dynamic scaling)</string>
<key>Persist</key>
<integer>1</integer>
@@ -8468,7 +8468,7 @@
<key>Value</key>
<integer>0</integer>
</map>
-
+
<key>RenderLocalLights</key>
<map>
<key>Comment</key>
@@ -8695,7 +8695,7 @@
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Boolean</string>
+ <string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
@@ -8732,7 +8732,7 @@
<key>Value</key>
<integer>0</integer>
</map>
-
+
<key>RenderAnimateRes</key>
<map>
<key>Comment</key>
@@ -8905,7 +8905,7 @@
<key>Value</key>
<integer>0</integer>
</map>
-
+
<key>RenderDepthOfField</key>
<map>
<key>Comment</key>
@@ -9034,7 +9034,7 @@
<key>Value</key>
<real>0.1</real>
</map>
-
+
<key>RenderHighlightBrightness</key>
<map>
<key>Comment</key>
@@ -9058,7 +9058,7 @@
<key>Value</key>
<real>0.6</real>
</map>
-
+
<key>RenderHighlightColor</key>
<map>
<key>Comment</key>
@@ -9087,7 +9087,7 @@
<key>Value</key>
<integer>0</integer>
</map>
-
+
<key>RenderSpecularResX</key>
<map>
<key>Comment</key>
@@ -9992,7 +9992,7 @@
<key>Value</key>
<integer>1</integer>
</map>
-
+
<key>RenderAutoMuteByteLimit</key>
<map>
<key>Comment</key>
@@ -10047,7 +10047,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
- </map>
+ </map>
<key>RenderAutoHideSurfaceAreaLimit</key>
<map>
<key>Comment</key>
@@ -10533,7 +10533,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
- </map>
+ </map>
<key>SelectMovableOnly</key>
<map>
<key>Comment</key>
@@ -10775,7 +10775,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
- </map>
+ </map>
<key>ShowCrosshairs</key>
<map>
<key>Comment</key>
@@ -10852,7 +10852,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
- </map>
+ </map>
<key>ShowMiniMapButton</key>
<map>
<key>Comment</key>
@@ -10919,7 +10919,7 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>ShowObjectRenderingCost</key>
+ <key>ShowObjectRenderingCost</key>
<map>
<key>Comment</key>
<string>Show the object rendering cost in build tools</string>
@@ -10928,9 +10928,9 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>1</integer>
- </map>
- <key>ShowNavbarFavoritesPanel</key>
+ <integer>1</integer>
+ </map>
+ <key>ShowNavbarFavoritesPanel</key>
<map>
<key>Comment</key>
<string>Show/hide navigation bar favorites panel</string>
@@ -10939,9 +10939,9 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>1</integer>
</map>
- <key>ShowNavbarNavigationPanel</key>
+ <key>ShowNavbarNavigationPanel</key>
<map>
<key>Comment</key>
<string>Show/hide navigation bar navigation panel</string>
@@ -10950,7 +10950,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>1</integer>
</map>
<key>ShowWorldMapButton</key>
<map>
@@ -11106,7 +11106,7 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>ShowPGSearchAll</key>
+ <key>ShowPGSearchAll</key>
<map>
<key>Comment</key>
<string>Display results of search All that are flagged as general</string>
@@ -11622,7 +11622,7 @@
<string>S32</string>
<key>Value</key>
<integer>0</integer>
- </map>
+ </map>
<key>SnapshotQuality</key>
<map>
<key>Comment</key>
@@ -12491,7 +12491,7 @@
<string>String</string>
<key>Value</key>
<string>B56AF90D-6684-48E4-B1E4-722D3DEB2CB6</string>
- </map>
+ </map>
<key>NearByChatChannelUUID</key>
<map>
<key>Comment</key>
@@ -12502,7 +12502,7 @@
<string>String</string>
<key>Value</key>
<string>E1158BD6-661C-4981-9DAD-4DCBFF062502</string>
- </map>
+ </map>
<key>NotificationChannelUUID</key>
<map>
<key>Comment</key>
@@ -12513,7 +12513,7 @@
<string>String</string>
<key>Value</key>
<string>AEED3193-8709-4693-8558-7452CCA97AE5</string>
- </map>
+ </map>
<key>AlertChannelUUID</key>
<map>
<key>Comment</key>
@@ -12524,7 +12524,7 @@
<string>String</string>
<key>Value</key>
<string>F3E07BC8-A973-476D-8C7F-F3B7293975D1</string>
- </map>
+ </map>
<key>UIImgWhiteUUID</key>
<map>
<key>Comment</key>
@@ -12546,7 +12546,7 @@
<string>S32</string>
<key>Value</key>
<integer>2</integer>
- </map>
+ </map>
<key>UIMaxComboWidth</key>
<map>
<key>Comment</key>
@@ -13459,7 +13459,7 @@
<string>String</string>
<key>Value</key>
<string>[i800,i600]</string>
- </map>
+ </map>
<key>sourceid</key>
<map>
<key>Comment</key>
@@ -14698,7 +14698,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
- </map>
+ </map>
<key>EnablePlaceProfile</key>
<map>
<key>Comment</key>
@@ -15520,7 +15520,7 @@
<key>Value</key>
<integer>0</integer>
</map>
-
+
<key>PathfindingLineWidth</key>
<map>
<key>Comment</key>
@@ -15561,7 +15561,7 @@
<real>1.0</real>
</array>
</map>
-
+
<key>HideUIControls</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 564e2450e8..be497fffc0 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -122,6 +122,9 @@
#include "llleap.h"
#include "stringize.h"
#include "llcoros.h"
+#if !LL_LINUX
+#include "cef/llceflib.h"
+#endif
// Third party library includes
#include <boost/bind.hpp>
@@ -129,7 +132,6 @@
#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>
-
#if LL_WINDOWS
# include <share.h> // For _SH_DENYWR in processMarkerFiles
#else
@@ -1700,6 +1702,9 @@ bool LLAppViewer::cleanup()
// to ensure shutdown order
LLMortician::setZealous(TRUE);
+ // Give any remaining SLPlugin instances a chance to exit cleanly.
+ LLPluginProcessParent::shutdown();
+
LLVoiceClient::getInstance()->terminate();
disconnectViewer();
@@ -2748,11 +2753,11 @@ bool LLAppViewer::initConfiguration()
//
gWindowTitle = LLTrans::getString("APP_NAME");
#if LL_DEBUG
- gWindowTitle += std::string(" [DEBUG]")
+ gWindowTitle += std::string(" [DEBUG]");
#endif
if (!gArgs.empty())
{
- gWindowTitle += std::string(" ") + gArgs;
+ gWindowTitle += std::string(" ") + gArgs;
}
LLStringUtil::truncate(gWindowTitle, 255);
@@ -3336,8 +3341,11 @@ LLSD LLAppViewer::getViewerInfo() const
info["VOICE_VERSION"] = LLTrans::getString("NotConnected");
}
- // TODO: Implement media plugin version query
- info["QT_WEBKIT_VERSION"] = "4.7.1 (version number hard-coded)";
+#if !LL_LINUX
+ info["LLCEFLIB_VERSION"] = LLCEFLIB_VERSION;
+#else
+ info["LLCEFLIB_VERSION"] = "Undefined";
+#endif
S32 packets_in = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_IN);
if (packets_in > 0)
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index dac610eda1..f7861fb4fd 100755
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -108,6 +108,7 @@
#include "llpluginclassmedia.h"
#include "llteleporthistorystorage.h"
#include "llproxy.h"
+#include "llweb.h"
#include "lllogininstance.h" // to check if logged in yet
#include "llsdserialize.h"
@@ -1942,6 +1943,16 @@ BOOL LLPanelPreference::postBuild()
gSavedSettings.getControl("ThrottleBandwidthKBPS")->getSignal()->connect(boost::bind(&LLPanelPreference::Updater::update, mBandWidthUpdater, _2));
}
+#ifdef EXTERNAL_TOS
+ LLRadioGroup* ext_browser_settings = getChild<LLRadioGroup>("preferred_browser_behavior");
+ if (ext_browser_settings)
+ {
+ // turn off ability to set external/internal browser
+ ext_browser_settings->setSelectedByValue(LLWeb::BROWSER_EXTERNAL_ONLY, true);
+ ext_browser_settings->setEnabled(false);
+ }
+#endif
+
apply();
return true;
}
diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp
index 5fa4441914..1743d0fc69 100755
--- a/indra/newview/llfloatertos.cpp
+++ b/indra/newview/llfloatertos.cpp
@@ -84,6 +84,20 @@ BOOL LLFloaterTOS::postBuild()
LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("tos_html");
if ( web_browser )
{
+// if we are forced to send users to an external site in their system browser
+// (e.g.) Linux users because of lack of media support for HTML ToS page
+// remove exisiting UI and replace with a link to external page where users can accept ToS
+#ifdef EXTERNAL_TOS
+ LLTextBox* header = getChild<LLTextBox>("tos_heading");
+ if (header)
+ header->setVisible(false);
+
+ LLTextBox* external_prompt = getChild<LLTextBox>("external_tos_required");
+ if (external_prompt)
+ external_prompt->setVisible(true);
+
+ web_browser->setVisible(false);
+#else
web_browser->addObserver(this);
// Don't use the start_url parameter for this browser instance -- it may finish loading before we get to add our observer.
@@ -95,6 +109,7 @@ BOOL LLFloaterTOS::postBuild()
// All links from tos_html should be opened in external browser
media_plugin->setOverrideClickTarget("_external");
}
+#endif
}
return TRUE;
@@ -102,6 +117,13 @@ BOOL LLFloaterTOS::postBuild()
void LLFloaterTOS::setSiteIsAlive( bool alive )
{
+// if we are forced to send users to an external site in their system browser
+// (e.g.) Linux users because of lack of media support for HTML ToS page
+// force the regular HTML UI to deactivate so alternative is rendered instead.
+#ifdef EXTERNAL_TOS
+ mSiteAlive = false;
+#else
+
mSiteAlive = alive;
// only do this for TOS pages
@@ -130,6 +152,7 @@ void LLFloaterTOS::setSiteIsAlive( bool alive )
tos_agreement->setEnabled( true );
}
}
+#endif
}
LLFloaterTOS::~LLFloaterTOS()
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 73faed7ef5..9cf3249983 100755
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -57,6 +57,7 @@
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llnotifications.h"
+#include "llnotificationsutil.h"
#include "lllineeditor.h"
#include "llfloaterwebcontent.h"
#include "llwindowshade.h"
@@ -428,6 +429,23 @@ BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask )
////////////////////////////////////////////////////////////////////////////////
//
+BOOL LLMediaCtrl::handleKeyUpHere(KEY key, MASK mask)
+{
+ BOOL result = FALSE;
+
+ if (mMediaSource)
+ {
+ result = mMediaSource->handleKeyUpHere(key, mask);
+ }
+
+ if (!result)
+ result = LLPanel::handleKeyUpHere(key, mask);
+
+ return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
void LLMediaCtrl::onVisibilityChange ( BOOL new_visibility )
{
LL_INFOS() << "visibility changed to " << (new_visibility?"true":"false") << LL_ENDL;
@@ -989,19 +1007,23 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
std::string uuid = self->getClickUUID();
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << target << "\", uri is " << url << LL_ENDL;
- LLNotification::Params notify_params;
- notify_params.name = "PopupAttempt";
- notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", mMediaTextureID);
- notify_params.functor.function = boost::bind(&LLMediaCtrl::onPopup, this, _1, _2);
-
- if (mTrusted)
- {
- LLNotifications::instance().forceResponse(notify_params, 0);
- }
- else
- {
- LLNotifications::instance().add(notify_params);
- }
+ LLWeb::loadURL(url, target, std::string());
+
+ // CP: removing this code because we no longer support popups so this breaks the flow.
+ // replaced with a bare call to LLWeb::LoadURL(...)
+ //LLNotification::Params notify_params;
+ //notify_params.name = "PopupAttempt";
+ //notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", mMediaTextureID);
+ //notify_params.functor.function = boost::bind(&LLMediaCtrl::onPopup, this, _1, _2);
+
+ //if (mTrusted)
+ //{
+ // LLNotifications::instance().forceResponse(notify_params, 0);
+ //}
+ //else
+ //{
+ // LLNotifications::instance().add(notify_params);
+ //}
break;
};
@@ -1072,6 +1094,13 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
};
break;
+ case MEDIA_EVENT_FILE_DOWNLOAD:
+ {
+ //llinfos << "Media event - file download requested - filename is " << self->getFileDownloadFilename() << llendl;
+ //LLNotificationsUtil::add("MediaFileDownloadUnsupported");
+ };
+ break;
+
case MEDIA_EVENT_DEBUG_MESSAGE:
{
LL_INFOS("media") << self->getDebugMessageText() << LL_ENDL;
@@ -1150,3 +1179,13 @@ void LLMediaCtrl::updateContextMenuParent(LLView* pNewParent)
{
mContextMenu->updateParent(pNewParent);
}
+
+bool LLMediaCtrl::wantsKeyUpKeyDown() const
+{
+ return true;
+}
+
+bool LLMediaCtrl::wantsReturnKey() const
+{
+ return true;
+}
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index 988733b85a..291d87073e 100755
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -151,6 +151,7 @@ public:
// over-rides
virtual BOOL handleKeyHere( KEY key, MASK mask);
+ virtual BOOL handleKeyUpHere(KEY key, MASK mask);
virtual void onVisibilityChange ( BOOL new_visibility );
virtual BOOL handleUnicodeCharHere(llwchar uni_char);
virtual void reshape( S32 width, S32 height, BOOL called_from_parent = TRUE);
@@ -171,6 +172,10 @@ public:
void updateContextMenuParent(LLView* pNewParent);
+ // The Browser windows want keyup and keydown events. Overridden from LLFocusableElement to return true.
+ virtual bool wantsKeyUpKeyDown() const;
+ virtual bool wantsReturnKey() const;
+
protected:
void convertInputCoords(S32& x, S32& y);
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 2081297717..4d41c792ca 100755
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -106,7 +106,7 @@ BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
mMouseDownX = x;
mMouseDownY = y;
- //left mouse down always picks transparent
+ //left mouse down always picks transparent (but see handleMouseUp)
mPick = gViewerWindow->pickImmediate(x, y, TRUE);
mPick.mKeyMask = mask;
@@ -661,30 +661,52 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
&& gAgentAvatarp
&& !gAgentAvatarp->isSitting()
&& !mBlockClickToWalk // another behavior hasn't cancelled click to walk
- && !mPick.mPosGlobal.isExactlyZero() // valid coordinates for pick
- && (mPick.mPickType == LLPickInfo::PICK_LAND // we clicked on land
- || mPick.mObjectID.notNull())) // or on an object
- {
- // handle special cases of steering picks
- LLViewerObject* avatar_object = mPick.getObject();
-
- // get pointer to avatar
- while (avatar_object && !avatar_object->isAvatar())
- {
- avatar_object = (LLViewerObject*)avatar_object->getParent();
- }
-
- if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf())
- {
- const F64 SELF_CLICK_WALK_DISTANCE = 3.0;
- // pretend we picked some point a bit in front of avatar
- mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE;
- }
- gAgentCamera.setFocusOnAvatar(TRUE, TRUE);
- walkToClickedLocation();
- LLFirstUse::notMoving(false);
-
- return TRUE;
+ )
+ {
+ // We may be doing click to walk, but we don't want to use a target on
+ // a transparent object because the user thought they were clicking on
+ // whatever they were seeing through it, so recompute what was clicked on
+ // ignoring transparent objects
+ LLPickInfo savedPick = mPick;
+ mPick = gViewerWindow->pickImmediate(savedPick.mMousePt.mX, savedPick.mMousePt.mY,
+ FALSE /* ignore transparent */,
+ FALSE /* ignore particles */);
+
+ if (!mPick.mPosGlobal.isExactlyZero() // valid coordinates for pick
+ && (mPick.mPickType == LLPickInfo::PICK_LAND // we clicked on land
+ || mPick.mObjectID.notNull())) // or on an object
+ {
+ // handle special cases of steering picks
+ LLViewerObject* avatar_object = mPick.getObject();
+
+ // get pointer to avatar
+ while (avatar_object && !avatar_object->isAvatar())
+ {
+ avatar_object = (LLViewerObject*)avatar_object->getParent();
+ }
+
+ if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf())
+ {
+ const F64 SELF_CLICK_WALK_DISTANCE = 3.0;
+ // pretend we picked some point a bit in front of avatar
+ mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE;
+ }
+ gAgentCamera.setFocusOnAvatar(TRUE, TRUE);
+ walkToClickedLocation();
+ LLFirstUse::notMoving(false);
+
+ return TRUE;
+ }
+ else
+ {
+ LL_DEBUGS("maint5901") << "walk target was "
+ << (mPick.mPosGlobal.isExactlyZero() ? "zero" : "not zero")
+ << ", pick type was " << (mPick.mPickType == LLPickInfo::PICK_LAND ? "land" : "not land")
+ << ", pick object was " << mPick.mObjectID
+ << LL_ENDL;
+ // we didn't click to walk, so restore the original target
+ mPick = savedPick;
+ }
}
gViewerWindow->setCursor(UI_CURSOR_ARROW);
if (hasMouseCapture())
@@ -716,14 +738,33 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
LL_INFOS() << "LLToolPie handleDoubleClick (becoming mouseDown)" << LL_ENDL;
}
+ if (handleMediaDblClick(mPick))
+ {
+ return TRUE;
+ }
+
if (gSavedSettings.getBOOL("DoubleClickAutoPilot"))
{
+ // We may be doing double click to walk, but we don't want to use a target on
+ // a transparent object because the user thought they were clicking on
+ // whatever they were seeing through it, so recompute what was clicked on
+ // ignoring transparent objects
+ LLPickInfo savedPick = mPick;
+ mPick = gViewerWindow->pickImmediate(savedPick.mMousePt.mX, savedPick.mMousePt.mY,
+ FALSE /* ignore transparent */,
+ FALSE /* ignore particles */);
+
if ((mPick.mPickType == LLPickInfo::PICK_LAND && !mPick.mPosGlobal.isExactlyZero()) ||
(mPick.mObjectID.notNull() && !mPick.mPosGlobal.isExactlyZero()))
{
walkToClickedLocation();
return TRUE;
}
+ else
+ {
+ // restore the original pick for any other purpose
+ mPick = savedPick;
+ }
}
else if (gSavedSettings.getBOOL("DoubleClickTeleport"))
{
@@ -1404,56 +1445,110 @@ static void handle_click_action_play()
bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
{
- //FIXME: how do we handle object in different parcel than us?
- LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
- LLPointer<LLViewerObject> objectp = pick.getObject();
-
-
- if (!parcel ||
- objectp.isNull() ||
- pick.mObjectFace < 0 ||
- pick.mObjectFace >= objectp->getNumTEs())
- {
- LLViewerMediaFocus::getInstance()->clearFocus();
-
- return false;
- }
-
- // Does this face have media?
- const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);
- if(!tep)
- return false;
-
- LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL;
- if(!mep)
- return false;
-
- viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
-
- if (gSavedSettings.getBOOL("MediaOnAPrimUI"))
- {
- if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) || media_impl.isNull())
- {
- // It's okay to give this a null impl
- LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal);
- }
- else
- {
- // Make sure keyboard focus is set to the media focus object.
- gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance());
- LLEditMenuHandler::gEditMenuHandler = LLViewerMediaFocus::instance().getFocusedMediaImpl();
-
- media_impl->mouseDown(pick.mUVCoords, gKeyboard->currentMask(TRUE));
- mMediaMouseCaptureID = mep->getMediaID();
- setMouseCapture(TRUE); // This object will send a mouse-up to the media when it loses capture.
- }
-
- return true;
- }
-
- LLViewerMediaFocus::getInstance()->clearFocus();
+ //FIXME: how do we handle object in different parcel than us?
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ LLPointer<LLViewerObject> objectp = pick.getObject();
+
+
+ if (!parcel ||
+ objectp.isNull() ||
+ pick.mObjectFace < 0 ||
+ pick.mObjectFace >= objectp->getNumTEs())
+ {
+ LLViewerMediaFocus::getInstance()->clearFocus();
+
+ return false;
+ }
+
+ // Does this face have media?
+ const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);
+ if (!tep)
+ return false;
+
+ LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL;
+ if (!mep)
+ return false;
+
+ viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
+
+ if (gSavedSettings.getBOOL("MediaOnAPrimUI"))
+ {
+ if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) || media_impl.isNull())
+ {
+ // It's okay to give this a null impl
+ LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal);
+ }
+ else
+ {
+ // Make sure keyboard focus is set to the media focus object.
+ gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance());
+ LLEditMenuHandler::gEditMenuHandler = LLViewerMediaFocus::instance().getFocusedMediaImpl();
+
+ media_impl->mouseDown(pick.mUVCoords, gKeyboard->currentMask(TRUE));
+ mMediaMouseCaptureID = mep->getMediaID();
+ setMouseCapture(TRUE); // This object will send a mouse-up to the media when it loses capture.
+ }
+
+ return true;
+ }
+
+ LLViewerMediaFocus::getInstance()->clearFocus();
+
+ return false;
+}
- return false;
+bool LLToolPie::handleMediaDblClick(const LLPickInfo& pick)
+{
+ //FIXME: how do we handle object in different parcel than us?
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ LLPointer<LLViewerObject> objectp = pick.getObject();
+
+
+ if (!parcel ||
+ objectp.isNull() ||
+ pick.mObjectFace < 0 ||
+ pick.mObjectFace >= objectp->getNumTEs())
+ {
+ LLViewerMediaFocus::getInstance()->clearFocus();
+
+ return false;
+ }
+
+ // Does this face have media?
+ const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);
+ if (!tep)
+ return false;
+
+ LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL;
+ if (!mep)
+ return false;
+
+ viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
+
+ if (gSavedSettings.getBOOL("MediaOnAPrimUI"))
+ {
+ if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) || media_impl.isNull())
+ {
+ // It's okay to give this a null impl
+ LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal);
+ }
+ else
+ {
+ // Make sure keyboard focus is set to the media focus object.
+ gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance());
+ LLEditMenuHandler::gEditMenuHandler = LLViewerMediaFocus::instance().getFocusedMediaImpl();
+
+ media_impl->mouseDoubleClick(pick.mUVCoords, gKeyboard->currentMask(TRUE));
+ mMediaMouseCaptureID = mep->getMediaID();
+ setMouseCapture(TRUE); // This object will send a mouse-up to the media when it loses capture.
+ }
+
+ return true;
+ }
+
+ LLViewerMediaFocus::getInstance()->clearFocus();
+
+ return false;
}
bool LLToolPie::handleMediaHover(const LLPickInfo& pick)
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index 68fe8bc4a5..c4a2f4a35b 100755
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -88,7 +88,8 @@ private:
ECursorType cursorFromObject(LLViewerObject* object);
bool handleMediaClick(const LLPickInfo& info);
- bool handleMediaHover(const LLPickInfo& info);
+ bool handleMediaDblClick(const LLPickInfo& info);
+ bool handleMediaHover(const LLPickInfo& info);
bool handleMediaMouseUp();
BOOL handleTooltipLand(std::string line, std::string tooltip_msg);
BOOL handleTooltipObject( LLViewerObject* hover_object, std::string line, std::string tooltip_msg);
diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp
index ada829eb4b..1ab672aafc 100755
--- a/indra/newview/llviewerkeyboard.cpp
+++ b/indra/newview/llviewerkeyboard.cpp
@@ -729,7 +729,10 @@ BOOL LLViewerKeyboard::handleKey(KEY translated_key, MASK translated_mask, BOOL
return mKeyHandledByUI[translated_key];
}
-
+BOOL LLViewerKeyboard::handleKeyUp(KEY translated_key, MASK translated_mask)
+{
+ return gViewerWindow->handleKeyUp(translated_key, translated_mask);
+}
BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name)
{
diff --git a/indra/newview/llviewerkeyboard.h b/indra/newview/llviewerkeyboard.h
index ca73212ed1..110dc89d28 100755
--- a/indra/newview/llviewerkeyboard.h
+++ b/indra/newview/llviewerkeyboard.h
@@ -89,6 +89,7 @@ public:
LLViewerKeyboard();
BOOL handleKey(KEY key, MASK mask, BOOL repeated);
+ BOOL handleKeyUp(KEY key, MASK mask);
S32 loadBindings(const std::string& filename); // returns number bound, 0 on error
S32 loadBindingsXML(const std::string& filename); // returns number bound, 0 on error
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 4e8fa28b86..014cf5a6bf 100755
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -5,21 +5,21 @@
* $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$
*/
@@ -66,6 +66,7 @@
#include "llvoavatar.h"
#include "llvoavatarself.h"
#include "llvovolume.h"
+#include "llfloaterreg.h"
#include "llwebprofile.h"
#include "llwindow.h"
#include "llvieweraudio.h"
@@ -181,7 +182,7 @@ static void remove_media_impl(LLViewerMediaImpl* media)
{
LLViewerMedia::impl_list::iterator iter = sViewerMediaImplList.begin();
LLViewerMedia::impl_list::iterator end = sViewerMediaImplList.end();
-
+
for(; iter != end; iter++)
{
if(media == *iter)
@@ -208,8 +209,8 @@ static bool sViewerMediaMuteListObserverInitialized = false;
// static
viewer_media_t LLViewerMedia::newMediaImpl(
const LLUUID& texture_id,
- S32 media_width,
- S32 media_height,
+ S32 media_width,
+ S32 media_height,
U8 media_auto_scale,
U8 media_loop)
{
@@ -233,24 +234,24 @@ viewer_media_t LLViewerMedia::newMediaImpl(
}
viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const std::string& previous_url, bool update_from_self)
-{
+{
// Try to find media with the same media ID
viewer_media_t media_impl = getMediaImplFromTextureID(media_entry->getMediaID());
-
- LL_DEBUGS() << "called, current URL is \"" << media_entry->getCurrentURL()
- << "\", previous URL is \"" << previous_url
+
+ LL_DEBUGS() << "called, current URL is \"" << media_entry->getCurrentURL()
+ << "\", previous URL is \"" << previous_url
<< "\", update_from_self is " << (update_from_self?"true":"false")
<< LL_ENDL;
-
+
bool was_loaded = false;
bool needs_navigate = false;
-
+
if(media_impl)
- {
+ {
was_loaded = media_impl->hasMedia();
-
+
media_impl->setHomeURL(media_entry->getHomeURL());
-
+
media_impl->mMediaAutoScale = media_entry->getAutoScale();
media_impl->mMediaLoop = media_entry->getAutoLoop();
media_impl->mMediaWidth = media_entry->getWidthPixels();
@@ -263,7 +264,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
media_impl->mMediaSource->setLoop(media_impl->mMediaLoop);
media_impl->mMediaSource->setSize(media_entry->getWidthPixels(), media_entry->getHeightPixels());
}
-
+
bool url_changed = (media_impl->mMediaEntryURL != previous_url);
if(media_impl->mMediaEntryURL.empty())
{
@@ -271,7 +272,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
{
// The current media URL is now empty. Unload the media source.
media_impl->unload();
-
+
LL_DEBUGS() << "Unloading media instance (new current URL is empty)." << LL_ENDL;
}
}
@@ -280,26 +281,26 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
// The current media URL is not empty.
// If (the media was already loaded OR the media was set to autoplay) AND this update didn't come from this agent,
// do a navigate.
- bool auto_play = media_impl->isAutoPlayable();
+ bool auto_play = media_impl->isAutoPlayable();
if((was_loaded || auto_play) && !update_from_self)
{
needs_navigate = url_changed;
}
-
- LL_DEBUGS() << "was_loaded is " << (was_loaded?"true":"false")
- << ", auto_play is " << (auto_play?"true":"false")
+
+ LL_DEBUGS() << "was_loaded is " << (was_loaded?"true":"false")
+ << ", auto_play is " << (auto_play?"true":"false")
<< ", needs_navigate is " << (needs_navigate?"true":"false") << LL_ENDL;
}
}
else
{
media_impl = newMediaImpl(
- media_entry->getMediaID(),
+ media_entry->getMediaID(),
media_entry->getWidthPixels(),
- media_entry->getHeightPixels(),
- media_entry->getAutoScale(),
+ media_entry->getHeightPixels(),
+ media_entry->getAutoScale(),
media_entry->getAutoLoop());
-
+
media_impl->setHomeURL(media_entry->getHomeURL());
media_impl->mMediaAutoPlay = media_entry->getAutoPlay();
media_impl->mMediaEntryURL = media_entry->getCurrentURL();
@@ -308,7 +309,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
needs_navigate = true;
}
}
-
+
if(media_impl)
{
if(needs_navigate)
@@ -327,7 +328,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
LL_DEBUGS() << "updating URL in the media impl to " << media_impl->mMediaEntryURL << LL_ENDL;
}
}
-
+
return media_impl;
}
@@ -336,7 +337,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
LLViewerMediaImpl* LLViewerMedia::getMediaImplFromTextureID(const LLUUID& texture_id)
{
LLViewerMediaImpl* result = NULL;
-
+
// Look up the texture ID in the texture id->impl map.
impl_id_map::iterator iter = sViewerMediaTextureIDMap.find(texture_id);
if(iter != sViewerMediaTextureIDMap.end())
@@ -351,7 +352,7 @@ LLViewerMediaImpl* LLViewerMedia::getMediaImplFromTextureID(const LLUUID& textur
// static
std::string LLViewerMedia::getCurrentUserAgent()
{
- // Don't use user-visible string to avoid
+ // Don't use user-visible string to avoid
// punctuation and strange characters.
std::string skin_name = gSavedSettings.getString("SkinCurrent");
@@ -370,7 +371,7 @@ std::string LLViewerMedia::getCurrentUserAgent()
codec << LLVersionInfo::getVersion();
codec << " (" << channel << "; " << skin_name << " skin)";
LL_INFOS() << codec.str() << LL_ENDL;
-
+
return codec.str();
}
@@ -379,7 +380,7 @@ std::string LLViewerMedia::getCurrentUserAgent()
void LLViewerMedia::updateBrowserUserAgent()
{
std::string user_agent = getCurrentUserAgent();
-
+
impl_list::iterator iter = sViewerMediaImplList.begin();
impl_list::iterator end = sViewerMediaImplList.end();
@@ -468,7 +469,7 @@ void LLViewerMedia::muteListChanged()
bool LLViewerMedia::isInterestingEnough(const LLVOVolume *object, const F64 &object_interest)
{
bool result = false;
-
+
if (NULL == object)
{
result = false;
@@ -484,13 +485,13 @@ bool LLViewerMedia::isInterestingEnough(const LLVOVolume *object, const F64 &obj
{
result = true;
}
- else
+ else
{
LL_DEBUGS() << "object interest = " << object_interest << ", lowest loadable = " << sLowestLoadableImplInterest << LL_ENDL;
if(object_interest >= sLowestLoadableImplInterest)
result = true;
}
-
+
return result;
}
@@ -597,13 +598,13 @@ static LLTrace::BlockTimerStatHandle FTM_MEDIA_MISC("Misc");
void LLViewerMedia::updateMedia(void *dummy_arg)
{
LL_RECORD_BLOCK_TIME(FTM_MEDIA_UPDATE);
-
+
// Enable/disable the plugin read thread
LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread"));
-
+
// HACK: we always try to keep a spare running webkit plugin around to improve launch times.
createSpareBrowserMediaSource();
-
+
sAnyMediaShowing = false;
sUpdatedCookies = getCookieStore()->getChangedCookies();
if(!sUpdatedCookies.empty())
@@ -611,7 +612,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
LL_DEBUGS() << "updated cookies will be sent to all loaded plugins: " << LL_ENDL;
LL_DEBUGS() << sUpdatedCookies << LL_ENDL;
}
-
+
impl_list::iterator iter = sViewerMediaImplList.begin();
impl_list::iterator end = sViewerMediaImplList.end();
@@ -624,14 +625,14 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
pimpl->calculateInterest();
}
}
-
+
// Let the spare media source actually launch
if(sSpareBrowserMediaSource)
{
LL_RECORD_BLOCK_TIME(FTM_MEDIA_SPARE_IDLE);
sSpareBrowserMediaSource->idle();
}
-
+
{
LL_RECORD_BLOCK_TIME(FTM_MEDIA_SORT);
// Sort the static instance list using our interest criteria
@@ -641,14 +642,14 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
// Go through the list again and adjust according to priority.
iter = sViewerMediaImplList.begin();
end = sViewerMediaImplList.end();
-
+
F64 total_cpu = 0.0f;
int impl_count_total = 0;
int impl_count_interest_low = 0;
int impl_count_interest_normal = 0;
-
+
std::vector<LLViewerMediaImpl*> proximity_order;
-
+
bool inworld_media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia");
bool inworld_audio_enabled = gSavedSettings.getBOOL("AudioStreamingMusic");
U32 max_instances = gSavedSettings.getU32("PluginInstancesTotal");
@@ -657,19 +658,19 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
F32 max_cpu = gSavedSettings.getF32("PluginInstancesCPULimit");
// Setting max_cpu to 0.0 disables CPU usage checking.
bool check_cpu_usage = (max_cpu != 0.0f);
-
+
LLViewerMediaImpl* lowest_interest_loadable = NULL;
-
+
// Notes on tweakable params:
// max_instances must be set high enough to allow the various instances used in the UI (for the help browser, search, etc.) to be loaded.
// If max_normal + max_low is less than max_instances, things will tend to get unloaded instead of being set to slideshow.
-
+
{
LL_RECORD_BLOCK_TIME(FTM_MEDIA_MISC);
for(; iter != end; iter++)
{
LLViewerMediaImpl* pimpl = *iter;
-
+
LLPluginClassMedia::EPriority new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
if(pimpl->isForcedUnloaded() || (impl_count_total >= (int)max_instances))
@@ -700,7 +701,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
else
{
// Look at interest and CPU usage for instances that aren't in any of the above states.
-
+
// Heuristic -- if the media texture's approximate screen area is less than 1/4 of the native area of the texture,
// turn it down to low instead of normal. This may downsample for plugins that support it.
bool media_is_small = false;
@@ -714,7 +715,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
{
media_is_small = true;
}
-
+
if(pimpl->getInterest() == 0.0f)
{
// This media is completely invisible, due to being outside the view frustrum or out of range.
@@ -736,11 +737,11 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
// The next max_low inworld get turned down
new_priority = LLPluginClassMedia::PRIORITY_LOW;
impl_count_interest_low++;
-
+
// Set the low priority size for downsampling to approximately the size the texture is displayed at.
{
F32 approximate_interest_dimension = (F32) sqrt(pimpl->getInterest());
-
+
pimpl->setLowPrioritySizeLimit(ll_round(approximate_interest_dimension));
}
}
@@ -750,18 +751,18 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
new_priority = LLPluginClassMedia::PRIORITY_SLIDESHOW;
}
}
-
+
if(!pimpl->getUsedInUI() && (new_priority != LLPluginClassMedia::PRIORITY_UNLOADED))
{
// This is a loadable inworld impl -- the last one in the list in this class defines the lowest loadable interest.
lowest_interest_loadable = pimpl;
-
+
impl_count_total++;
}
// Overrides if the window is minimized or we lost focus (taking care
// not to accidentally "raise" the priority either)
- if (!gViewerWindow->getActive() /* viewer window minimized? */
+ if (!gViewerWindow->getActive() /* viewer window minimized? */
&& new_priority > LLPluginClassMedia::PRIORITY_HIDDEN)
{
new_priority = LLPluginClassMedia::PRIORITY_HIDDEN;
@@ -771,7 +772,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
{
new_priority = LLPluginClassMedia::PRIORITY_LOW;
}
-
+
if(!inworld_media_enabled)
{
// If inworld media is locked out, force all inworld media to stay unloaded.
@@ -789,7 +790,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
}
}
pimpl->setPriority(new_priority);
-
+
if(pimpl->getUsedInUI())
{
// Any impls used in the UI should not be in the proximity list.
@@ -801,7 +802,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
}
total_cpu += pimpl->getCPUUsage();
-
+
if (!pimpl->getUsedInUI() && pimpl->hasMedia())
{
sAnyMediaShowing = true;
@@ -825,7 +826,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
sLowestLoadableImplInterest = object->getPixelArea();
}
}
-
+
if(gSavedSettings.getBOOL("MediaPerformanceManagerDebug"))
{
// Give impls the same ordering as the priority list
@@ -834,7 +835,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
else
{
LL_RECORD_BLOCK_TIME(FTM_MEDIA_SORT2);
- // Use a distance-based sort for proximity values.
+ // Use a distance-based sort for proximity values.
std::stable_sort(proximity_order.begin(), proximity_order.end(), proximity_comparitor);
}
@@ -843,7 +844,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
{
proximity_order[i]->mProximity = i;
}
-
+
LL_DEBUGS("PluginPriority") << "Total reported CPU usage is " << total_cpu << LL_ENDL;
}
@@ -862,11 +863,11 @@ void LLViewerMedia::setAllMediaEnabled(bool val)
// Set "tentative" autoplay first. We need to do this here or else
// re-enabling won't start up the media below.
gSavedSettings.setBOOL("MediaTentativeAutoPlay", val);
-
- // Then
+
+ // Then
impl_list::iterator iter = sViewerMediaImplList.begin();
impl_list::iterator end = sViewerMediaImplList.end();
-
+
for(; iter != end; iter++)
{
LLViewerMediaImpl* pimpl = *iter;
@@ -875,18 +876,18 @@ void LLViewerMedia::setAllMediaEnabled(bool val)
pimpl->setDisabled(!val);
}
}
-
+
// Also do Parcel Media and Parcel Audio
if (val)
{
if (!LLViewerMedia::isParcelMediaPlaying() && LLViewerMedia::hasParcelMedia())
- {
+ {
LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel());
}
-
+
if (gSavedSettings.getBOOL("AudioStreamingMusic") &&
!LLViewerMedia::isParcelAudioPlaying() &&
- gAudiop &&
+ gAudiop &&
LLViewerMedia::hasParcelAudio())
{
if (LLAudioEngine::AUDIO_PAUSED == gAudiop->isInternetStreamPlaying())
@@ -959,26 +960,26 @@ void LLViewerMedia::clearAllCookies()
pimpl->mMediaSource->clear_cookies();
}
}
-
+
// Clear all cookies from the cookie store
getCookieStore()->setAllCookies("");
// FIXME: this may not be sufficient, since the on-disk cookie file won't get written until some browser instance exits cleanly.
// It also won't clear cookies for other accounts, or for any account if we're not logged in, and won't do anything at all if there are no webkit plugins loaded.
// Until such time as we can centralize cookie storage, the following hack should cover these cases:
-
+
// HACK: Look for cookie files in all possible places and delete them.
// NOTE: this assumes knowledge of what happens inside the webkit plugin (it's what adds 'browser_profile' to the path and names the cookie file)
-
+
// Places that cookie files can be:
// <getOSUserAppDir>/browser_profile/cookies
// <getOSUserAppDir>/first_last/browser_profile/cookies (note that there may be any number of these!)
// <getOSUserAppDir>/first_last/plugin_cookies.txt (note that there may be any number of these!)
-
+
std::string base_dir = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter();
std::string target;
std::string filename;
-
+
LL_DEBUGS() << "base dir = " << base_dir << LL_ENDL;
// The non-logged-in version is easy
@@ -991,7 +992,7 @@ void LLViewerMedia::clearAllCookies()
{
LLFile::remove(target);
}
-
+
// the hard part: iterate over all user directories and delete the cookie file from each one
LLDirIterator dir_iter(base_dir, "*_*");
while (dir_iter.next(filename))
@@ -1001,26 +1002,26 @@ void LLViewerMedia::clearAllCookies()
gDirUtilp->append(target, "cookies");
LL_DEBUGS() << "target = " << target << LL_ENDL;
if(LLFile::isfile(target))
- {
+ {
LLFile::remove(target);
}
-
+
// Other accounts may have new-style cookie files too -- delete them as well
target = gDirUtilp->add(base_dir, filename);
gDirUtilp->append(target, PLUGIN_COOKIE_FILE_NAME);
LL_DEBUGS() << "target = " << target << LL_ENDL;
if(LLFile::isfile(target))
- {
+ {
LLFile::remove(target);
}
}
-
+
// If we have an OpenID cookie, re-add it to the cookie store.
- setOpenIDCookie();
+ setOpenIDCookie(std::string());
}
-
+
/////////////////////////////////////////////////////////////////////////////////////////
-// static
+// static
void LLViewerMedia::clearAllCaches()
{
// Clear all plugins' caches
@@ -1032,9 +1033,9 @@ void LLViewerMedia::clearAllCaches()
pimpl->clearCache();
}
}
-
+
/////////////////////////////////////////////////////////////////////////////////////////
-// static
+// static
void LLViewerMedia::setCookiesEnabled(bool enabled)
{
// Set the "cookies enabled" flag for all loaded plugins
@@ -1049,9 +1050,9 @@ void LLViewerMedia::setCookiesEnabled(bool enabled)
}
}
}
-
+
/////////////////////////////////////////////////////////////////////////////////////////
-// static
+// static
void LLViewerMedia::setProxyConfig(bool enable, const std::string &host, int port)
{
// Set the proxy config for all loaded plugins
@@ -1068,7 +1069,7 @@ void LLViewerMedia::setProxyConfig(bool enable, const std::string &host, int por
}
/////////////////////////////////////////////////////////////////////////////////////////
-// static
+// static
/////////////////////////////////////////////////////////////////////////////////////////
// static
LLPluginCookieStore *LLViewerMedia::getCookieStore()
@@ -1077,7 +1078,7 @@ LLPluginCookieStore *LLViewerMedia::getCookieStore()
{
sCookieStore = new LLPluginCookieStore;
}
-
+
return sCookieStore;
}
@@ -1093,7 +1094,7 @@ void LLViewerMedia::loadCookieFile()
LL_INFOS() << "can't get path to plugin cookie file - probably not logged in yet." << LL_ENDL;
return;
}
-
+
// open the file for reading
llifstream file(resolved_filename.c_str());
if (!file.is_open())
@@ -1101,11 +1102,11 @@ void LLViewerMedia::loadCookieFile()
LL_WARNS() << "can't load plugin cookies from file \"" << PLUGIN_COOKIE_FILE_NAME << "\"" << LL_ENDL;
return;
}
-
+
getCookieStore()->readAllCookies(file, true);
file.close();
-
+
// send the clear_cookies message to all loaded plugins
impl_list::iterator iter = sViewerMediaImplList.begin();
impl_list::iterator end = sViewerMediaImplList.end();
@@ -1117,9 +1118,9 @@ void LLViewerMedia::loadCookieFile()
pimpl->mMediaSource->clear_cookies();
}
}
-
+
// If we have an OpenID cookie, re-add it to the cookie store.
- setOpenIDCookie();
+ setOpenIDCookie(std::string());
}
@@ -1154,23 +1155,23 @@ void LLViewerMedia::saveCookieFile()
void LLViewerMedia::addCookie(const std::string &name, const std::string &value, const std::string &domain, const LLDate &expires, const std::string &path, bool secure)
{
std::stringstream cookie;
-
+
cookie << name << "=" << LLPluginCookieStore::quoteString(value);
-
+
if(expires.notNull())
{
cookie << "; expires=" << expires.asRFC1123();
}
-
+
cookie << "; domain=" << domain;
cookie << "; path=" << path;
-
+
if(secure)
{
cookie << "; secure";
}
-
+
getCookieStore()->setCookies(cookie.str());
}
@@ -1187,7 +1188,7 @@ void LLViewerMedia::addSessionCookie(const std::string &name, const std::string
void LLViewerMedia::removeCookie(const std::string &name, const std::string &domain, const std::string &path )
{
// To remove a cookie, add one with the same name, domain, and path that expires in the past.
-
+
addCookie(name, "", domain, LLDate(LLDate::now().secondsSinceEpoch() - 1.0), path);
}
@@ -1205,6 +1206,30 @@ LLSD LLViewerMedia::getHeaders()
return headers;
}
+ /////////////////////////////////////////////////////////////////////////////////////////
+ // static
+bool LLViewerMedia::parseRawCookie(const std::string raw_cookie, std::string& name, std::string& value, std::string& path, bool& httponly, bool& secure)
+{
+ std::size_t name_pos = raw_cookie.find_first_of("=");
+ if (name_pos != std::string::npos)
+ {
+ name = raw_cookie.substr(0, name_pos);
+ std::size_t value_pos = raw_cookie.find_first_of(";", name_pos);
+ if (value_pos != std::string::npos)
+ {
+ value = raw_cookie.substr(name_pos + 1, value_pos - name_pos - 1);
+ path = "/"; // assume root path for now
+
+ httponly = true; // hard coded for now
+ secure = true;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
LLCore::HttpHeaders::ptr_t LLViewerMedia::getHttpHeaders()
{
LLCore::HttpHeaders::ptr_t headers(new LLCore::HttpHeaders);
@@ -1217,9 +1242,10 @@ LLCore::HttpHeaders::ptr_t LLViewerMedia::getHttpHeaders()
return headers;
}
+
/////////////////////////////////////////////////////////////////////////////////////////
// static
-void LLViewerMedia::setOpenIDCookie()
+void LLViewerMedia::setOpenIDCookie(const std::string& url)
{
if(!sOpenIDCookie.empty())
{
@@ -1260,6 +1286,7 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url)
}
else
{ // Hostname starts after the @.
+ // Hostname starts after the @.
// (If the hostname part is empty, this may put host_start at the end of the string. In that case, it will end up passing through an empty hostname, which is correct.)
++hostStart;
}
@@ -1271,7 +1298,30 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url)
getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(hostStart, hostEnd - hostStart));
- // Do a web profile get so we can store the cookie
+ if (url.length())
+ {
+ LLMediaCtrl* media_instance = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents");
+ if (media_instance)
+ {
+ std::string cookie_host = authority.substr(hostStart, hostEnd - hostStart);
+ std::string cookie_name = "";
+ std::string cookie_value = "";
+ std::string cookie_path = "";
+ bool httponly = true;
+ bool secure = true;
+ if (parseRawCookie(sOpenIDCookie, cookie_name, cookie_value, cookie_path, httponly, secure) &&
+ media_instance->getMediaPlugin())
+ {
+ media_instance->getMediaPlugin()->setCookie(url, cookie_name, cookie_value, cookie_host, cookie_path, httponly, secure);
+ }
+ }
+ }
+
+ // NOTE: this is the original OpenID cookie code, so of which is no longer needed now that we
+ // are using CEF - it's very intertwined with other code so, for the moment, I'm going to
+ // leave it alone and make a task to come back to it once we're sure the CEF cookie code is robust.
+
+ // Do a web profile get so we can store the cookie
httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, "*/*");
httpHeaders->append(HTTP_OUT_HEADER_COOKIE, sOpenIDCookie);
httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, getCurrentUserAgent());
@@ -1332,10 +1382,11 @@ void LLViewerMedia::openIDSetupCoro(std::string openidUrl, std::string openidTok
httpOpts->setWantHeaders(true);
- // post the token to the url
+ // post the token to the url
// the responder will need to extract the cookie(s).
// Save the OpenID URL for later -- we may need the host when adding the cookie.
sOpenIDURL.init(openidUrl.c_str());
+
// We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies.
sOpenIDCookie.clear();
@@ -1366,22 +1417,23 @@ void LLViewerMedia::openIDSetupCoro(std::string openidUrl, std::string openidTok
}
// We don't care about the content of the response, only the Set-Cookie header.
- const std::string &cookie = resultHeaders[HTTP_IN_HEADER_SET_COOKIE];
+ const std::string& cookie = resultHeaders[HTTP_IN_HEADER_SET_COOKIE].asString();
- // *TODO: What about bad status codes? Does this destroy previous cookies?
- LLViewerMedia::openIDCookieResponse(cookie);
+ // *TODO: What about bad status codes? Does this destroy previous cookies?
+ LLViewerMedia::openIDCookieResponse(openidUrl, cookie);
LL_DEBUGS("MediaAuth") << "OpenID cookie set." << LL_ENDL;
+
}
/////////////////////////////////////////////////////////////////////////////////////////
// static
-void LLViewerMedia::openIDCookieResponse(const std::string &cookie)
+void LLViewerMedia::openIDCookieResponse(const std::string& url, const std::string &cookie)
{
LL_DEBUGS("MediaAuth") << "Cookie received: \"" << cookie << "\"" << LL_ENDL;
-
+
sOpenIDCookie += cookie;
- setOpenIDCookie();
+ setOpenIDCookie(url);
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -1390,7 +1442,7 @@ void LLViewerMedia::proxyWindowOpened(const std::string &target, const std::stri
{
if(uuid.empty())
return;
-
+
for (impl_list::iterator iter = sViewerMediaImplList.begin(); iter != sViewerMediaImplList.end(); iter++)
{
if((*iter)->mMediaSource && (*iter)->mMediaSource->pluginSupportsMediaBrowser())
@@ -1427,7 +1479,7 @@ void LLViewerMedia::createSpareBrowserMediaSource()
if (!sSpareBrowserMediaSource && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))
{
// The null owner will keep the browser plugin from fully initializing
- // (specifically, it keeps LLPluginClassMedia from negotiating a size change,
+ // (specifically, it keeps LLPluginClassMedia from negotiating a size change,
// which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color)
sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType(HTTP_CONTENT_TEXT_HTML, NULL, 0, 0);
}
@@ -1439,7 +1491,7 @@ LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource()
{
LLPluginClassMedia* result = sSpareBrowserMediaSource;
sSpareBrowserMediaSource = NULL;
- return result;
+ return result;
};
bool LLViewerMedia::hasInWorldMedia()
@@ -1528,12 +1580,12 @@ void LLViewerMedia::setOnlyAudibleMediaTextureID(const LLUUID& texture_id)
//////////////////////////////////////////////////////////////////////////////////////////
// LLViewerMediaImpl
//////////////////////////////////////////////////////////////////////////////////////////
-LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id,
- S32 media_width,
- S32 media_height,
- U8 media_auto_scale,
+LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id,
+ S32 media_width,
+ S32 media_height,
+ U8 media_auto_scale,
U8 media_loop)
-:
+:
mMediaSource( NULL ),
mMovieImageHasMips(false),
mMediaWidth(media_width),
@@ -1583,11 +1635,11 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id,
LLMuteList::getInstance()->addObserver(&sViewerMediaMuteListObserver);
sViewerMediaMuteListObserverInitialized = true;
}
-
+
add_media_impl(this);
setTextureID(texture_id);
-
+
// connect this media_impl to the media texture, creating it if it doesn't exist.0
// This is necessary because we need to be able to use getMaxVirtualSize() even if the media plugin is not loaded.
LLViewerMediaTexture* media_tex = LLViewerTextureManager::getMediaTexture(mTextureId);
@@ -1602,7 +1654,7 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id,
LLViewerMediaImpl::~LLViewerMediaImpl()
{
destroyMediaSource();
-
+
LLViewerMediaTexture::removeMediaImplFromTexture(mTextureId) ;
setTextureID();
@@ -1614,7 +1666,7 @@ void LLViewerMediaImpl::emitEvent(LLPluginClassMedia* plugin, LLViewerMediaObser
{
// Broadcast to observers using the superclass version
LLViewerMediaEventEmitter::emitEvent(plugin, event);
-
+
// If this media is on one or more LLVOVolume objects, tell them about the event as well.
std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
while(iter != mObjectList.end())
@@ -1630,7 +1682,7 @@ bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type)
{
bool mimeTypeChanged = (mMimeType != mime_type);
bool pluginChanged = (LLMIMETypes::implType(mCurrentMimeType) != LLMIMETypes::implType(mime_type));
-
+
if(!mMediaSource || pluginChanged)
{
// We don't have a plugin at all, or the new mime type is handled by a different plugin than the old mime type.
@@ -1653,7 +1705,7 @@ void LLViewerMediaImpl::createMediaSource()
// This media shouldn't be created yet.
return;
}
-
+
if(! mMediaURL.empty())
{
navigateInternal();
@@ -1679,15 +1731,15 @@ void LLViewerMediaImpl::destroyMediaSource()
{
oldImage->setPlaying(FALSE) ;
}
-
+
cancelMimeTypeProbe();
-
+
if(mMediaSource)
{
mMediaSource->setDeleteOK(true) ;
delete mMediaSource;
mMediaSource = NULL;
- }
+ }
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -1702,11 +1754,11 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
{
std::string plugin_basename = LLMIMETypes::implType(media_type);
LLPluginClassMedia* media_source = NULL;
-
+
// HACK: we always try to keep a spare running webkit plugin around to improve launch times.
// If a spare was already created before PluginAttachDebuggerToPlugins was set, don't use it.
// Do not use a spare if launching with full viewer control (e.g. Facebook, Twitter and few others)
- if ((plugin_basename == "media_plugin_webkit") &&
+ if ((plugin_basename == "media_plugin_cef") &&
!gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins") && !clean_browser)
{
media_source = LLViewerMedia::getSpareBrowserMediaSource();
@@ -1715,7 +1767,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
media_source->setOwner(owner);
media_source->setTarget(target);
media_source->setSize(default_width, default_height);
-
+
return media_source;
}
}
@@ -1727,8 +1779,12 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
{
std::string launcher_name = gDirUtilp->getLLPluginLauncher();
std::string plugin_name = gDirUtilp->getLLPluginFilename(plugin_basename);
- std::string user_data_path = gDirUtilp->getOSUserAppDir();
- user_data_path += gDirUtilp->getDirDelimiter();
+
+ std::string user_data_path_cache = gDirUtilp->getCacheDir(false);
+ user_data_path_cache += gDirUtilp->getDirDelimiter();
+
+ std::string user_data_path_cookies = gDirUtilp->getOSUserAppDir();
+ user_data_path_cookies += gDirUtilp->getDirDelimiter();
// Fix for EXT-5960 - make browser profile specific to user (cache, cookies etc.)
// If the linden username returned is blank, that can only mean we are
@@ -1739,8 +1795,8 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
if ( ! linden_user_dir.empty() )
{
// gDirUtilp->getLindenUserDir() is whole path, not just Linden name
- user_data_path = linden_user_dir;
- user_data_path += gDirUtilp->getDirDelimiter();
+ user_data_path_cookies = linden_user_dir;
+ user_data_path_cookies += gDirUtilp->getDirDelimiter();
};
// See if the plugin executable exists
@@ -1757,7 +1813,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
{
media_source = new LLPluginClassMedia(owner);
media_source->setSize(default_width, default_height);
- media_source->setUserDataPath(user_data_path);
+ media_source->setUserDataPath(user_data_path_cache, user_data_path_cookies);
media_source->setLanguageCode(LLUI::getLanguage());
// collect 'cookies enabled' setting from prefs and send to embedded browser
@@ -1771,12 +1827,15 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
// collect 'javascript enabled' setting from prefs and send to embedded browser
bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" );
media_source->setJavascriptEnabled( javascript_enabled || clean_browser);
-
+
bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging");
media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled || clean_browser);
+ // need to set agent string here before instance created
+ media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent());
+
media_source->setTarget(target);
-
+
const std::string plugin_dir = gDirUtilp->getLLPluginDir();
if (media_source->init(launcher_name, plugin_dir, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins")))
{
@@ -1789,14 +1848,14 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
}
}
}
-
+
LL_WARNS_ONCE("Plugin") << "plugin initialization failed for mime type: " << media_type << LL_ENDL;
LLSD args;
args["MIME_TYPE"] = media_type;
LLNotificationsUtil::add("NoPlugin", args);
return NULL;
-}
+}
//////////////////////////////////////////////////////////////////////////////////////////
bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
@@ -1807,10 +1866,10 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
mMediaWidth = mMediaSource->getSetWidth();
mMediaHeight = mMediaSource->getSetHeight();
}
-
+
// Always delete the old media impl first.
destroyMediaSource();
-
+
// and unconditionally set the mime type
mMimeType = media_type;
@@ -1818,7 +1877,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
{
// This impl should not be loaded at this time.
LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL;
-
+
return false;
}
@@ -1829,7 +1888,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
mCurrentMimeType = mMimeType;
LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mTarget, mCleanBrowser);
-
+
if (media_source)
{
media_source->setDisableTimeout(gSavedSettings.getBOOL("DebugPluginDisableTimeout"));
@@ -1838,7 +1897,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent());
media_source->focus(mHasFocus);
media_source->setBackgroundColor(mBackgroundColor);
-
+
if(gSavedSettings.getBOOL("BrowserIgnoreSSLCertErrors"))
{
media_source->ignore_ssl_cert_errors(true);
@@ -1846,19 +1905,19 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
// the correct way to deal with certs it to load ours from CA.pem and append them to the ones
// Qt/WebKit loads from your system location.
- // Note: This needs the new CA.pem file with the Equifax Secure Certificate Authority
+ // Note: This needs the new CA.pem file with the Equifax Secure Certificate Authority
// cert at the bottom: (MIIDIDCCAomgAwIBAgIENd70zzANBg)
std::string ca_path = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "CA.pem" );
media_source->addCertificateFilePath( ca_path );
media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort"));
-
+
if(mClearCache)
{
mClearCache = false;
media_source->clear_cache();
}
-
+
// TODO: Only send cookies to plugins that need them
// Ideally, the plugin should tell us whether it handles cookies or not -- either via the init response or through a separate message.
// Due to the ordering of messages, it's possible we wouldn't get that information back in time to send cookies before sending a navigate message,
@@ -1869,7 +1928,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
{
media_source->set_cookies(all_cookies);
}
-
+
mMediaSource = media_source;
mMediaSource->setDeleteOK(false) ;
updateVolume();
@@ -1912,16 +1971,16 @@ void LLViewerMediaImpl::loadURI()
std::string sanitized_uri = (u.query().empty() ? uri : u.scheme() + "://" + u.authority() + u.path());
LL_INFOS() << "Asking media source to load URI: " << sanitized_uri << LL_ENDL;
}
-
+
mMediaSource->loadURI( uri );
-
- // A non-zero mPreviousMediaTime means that either this media was previously unloaded by the priority code while playing/paused,
+
+ // A non-zero mPreviousMediaTime means that either this media was previously unloaded by the priority code while playing/paused,
// or a seek happened before the media loaded. In either case, seek to the saved time.
if(mPreviousMediaTime != 0.0f)
{
seek(mPreviousMediaTime);
}
-
+
if(mPreviousMediaState == MEDIA_PLAYING)
{
// This media was playing before this instance was unloaded.
@@ -1974,11 +2033,11 @@ void LLViewerMediaImpl::play()
// This may be the case where the plugin's priority is PRIORITY_UNLOADED
return;
}
-
+
// Only do this if the media source was just loaded.
loadURI();
}
-
+
// always start the media
start();
}
@@ -2079,10 +2138,10 @@ void LLViewerMediaImpl::updateVolume()
{
if(mMediaSource)
{
- // always scale the volume by the global media volume
+ // always scale the volume by the global media volume
F32 volume = mRequestedVolume * LLViewerMedia::getVolume();
- if (mProximityCamera > 0)
+ if (mProximityCamera > 0)
{
if (mProximityCamera > gSavedSettings.getF32("MediaRollOffMax"))
{
@@ -2121,7 +2180,7 @@ F32 LLViewerMediaImpl::getVolume()
void LLViewerMediaImpl::focus(bool focus)
{
mHasFocus = focus;
-
+
if (mMediaSource)
{
// call focus just for the hell of it, even though this apopears to be a nop
@@ -2149,7 +2208,7 @@ std::string LLViewerMediaImpl::getCurrentMediaURL()
{
return mCurrentMediaURL;
}
-
+
return mMediaURL;
}
@@ -2217,17 +2276,17 @@ void LLViewerMediaImpl::mouseMove(S32 x, S32 y, MASK mask)
}
//////////////////////////////////////////////////////////////////////////////////////////
-//static
+//static
void LLViewerMediaImpl::scaleTextureCoords(const LLVector2& texture_coords, S32 *x, S32 *y)
{
F32 texture_x = texture_coords.mV[VX];
F32 texture_y = texture_coords.mV[VY];
-
+
// Deal with repeating textures by wrapping the coordinates into the range [0, 1.0)
texture_x = fmodf(texture_x, 1.0f);
if(texture_x < 0.0f)
texture_x = 1.0 + texture_x;
-
+
texture_y = fmodf(texture_y, 1.0f);
if(texture_y < 0.0f)
texture_y = 1.0 + texture_y;
@@ -2255,7 +2314,7 @@ void LLViewerMediaImpl::mouseDown(const LLVector2& texture_coords, MASK mask, S3
void LLViewerMediaImpl::mouseUp(const LLVector2& texture_coords, MASK mask, S32 button)
{
if(mMediaSource)
- {
+ {
S32 x, y;
scaleTextureCoords(texture_coords, &x, &y);
@@ -2266,7 +2325,7 @@ void LLViewerMediaImpl::mouseUp(const LLVector2& texture_coords, MASK mask, S32
void LLViewerMediaImpl::mouseMove(const LLVector2& texture_coords, MASK mask)
{
if(mMediaSource)
- {
+ {
S32 x, y;
scaleTextureCoords(texture_coords, &x, &y);
@@ -2274,6 +2333,17 @@ void LLViewerMediaImpl::mouseMove(const LLVector2& texture_coords, MASK mask)
}
}
+void LLViewerMediaImpl::mouseDoubleClick(const LLVector2& texture_coords, MASK mask)
+{
+ if (mMediaSource)
+ {
+ S32 x, y;
+ scaleTextureCoords(texture_coords, &x, &y);
+
+ mouseDoubleClick(x, y, mask);
+ }
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button)
{
@@ -2308,18 +2378,18 @@ void LLViewerMediaImpl::onMouseCaptureLost()
}
//////////////////////////////////////////////////////////////////////////////////////////
-BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask)
-{
+BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask)
+{
// NOTE: this is called when the mouse is released when we have capture.
// Due to the way mouse coordinates are mapped to the object, we can't use the x and y coordinates that come in with the event.
-
+
if(hasMouseCapture())
{
// Release the mouse -- this will also send a mouseup to the media
gFocusMgr.setMouseCapture( FALSE );
}
- return TRUE;
+ return TRUE;
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -2395,14 +2465,14 @@ void LLViewerMediaImpl::updateJavascriptObject()
}
//////////////////////////////////////////////////////////////////////////////////////////
-const std::string& LLViewerMediaImpl::getName() const
-{
+const std::string& LLViewerMediaImpl::getName() const
+{
if (mMediaSource)
{
return mMediaSource->getMediaName();
}
-
- return LLStringUtil::null;
+
+ return LLStringUtil::null;
};
//////////////////////////////////////////////////////////////////////////////////////////
@@ -2458,21 +2528,21 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
// Don't carry media play state across distinct URLs.
resetPreviousMediaState();
}
-
+
// Always set the current URL and MIME type.
mMediaURL = url;
mMimeType = mime_type;
mCleanBrowser = clean_browser;
-
+
// Clear the current media URL, since it will no longer be correct.
mCurrentMediaURL.clear();
-
+
// if mime type discovery was requested, we'll need to do it when the media loads
mNavigateRediscoverType = rediscover_type;
-
+
// and if this was a server request, the navigate on load will also need to be one.
mNavigateServerRequest = server_request;
-
+
// An explicit navigate resets the "failed" flag.
mMediaSourceFailed = false;
@@ -2488,7 +2558,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
// This impl should not be loaded at this time.
LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL;
-
+
return;
}
@@ -2519,7 +2589,7 @@ void LLViewerMediaImpl::navigateInternal()
LL_WARNS() << "MIME type probe already in progress -- bailing out." << LL_ENDL;
return;
}
-
+
if(mNavigateServerRequest)
{
setNavState(MEDIANAVSTATE_SERVER_SENT);
@@ -2528,12 +2598,12 @@ void LLViewerMediaImpl::navigateInternal()
{
setNavState(MEDIANAVSTATE_NONE);
}
-
+
// If the caller has specified a non-empty MIME type, look that up in our MIME types list.
// If we have a plugin for that MIME type, use that instead of attempting auto-discovery.
// This helps in supporting legacy media content where the server the media resides on returns a bogus MIME type
// but the parcel owner has correctly set the MIME type in the parcel media settings.
-
+
if(!mMimeType.empty() && (mMimeType != LLMIMETypes::getDefaultMimeType()))
{
std::string plugin_basename = LLMIMETypes::implType(mMimeType);
@@ -2671,27 +2741,47 @@ void LLViewerMediaImpl::navigateStop()
bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask)
{
bool result = false;
-
+
if (mMediaSource)
{
// FIXME: THIS IS SO WRONG.
// Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it...
- if( MASK_CONTROL & mask && key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END)
+ if (MASK_CONTROL & mask && key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END)
{
result = true;
}
-
- if(!result)
+
+ if (!result)
+ {
+ LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData();
+ result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN, key, mask, native_key_data);
+ }
+ }
+
+ return result;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::handleKeyUpHere(KEY key, MASK mask)
+{
+ bool result = false;
+
+ if (mMediaSource)
+ {
+ // FIXME: THIS IS SO WRONG.
+ // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it...
+ if (MASK_CONTROL & mask && key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END)
+ {
+ result = true;
+ }
+
+ if (!result)
{
-
LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData();
-
- result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask, native_key_data);
- // Since the viewer internal event dispatching doesn't give us key-up events, simulate one here.
- (void)mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_UP ,key, mask, native_key_data);
+ result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_UP, key, mask, native_key_data);
}
}
-
+
return result;
}
@@ -2699,7 +2789,7 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask)
bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char)
{
bool result = false;
-
+
if (mMediaSource)
{
// only accept 'printable' characters, sigh...
@@ -2707,11 +2797,11 @@ bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char)
&& uni_char != 127) // SDL thinks this is 'delete' - yuck.
{
LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData();
-
+
mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char)), gKeyboard->currentMask(FALSE), native_key_data);
}
}
-
+
return result;
}
@@ -2790,15 +2880,15 @@ void LLViewerMediaImpl::update()
}
}
-
+
if(mMediaSource == NULL)
{
return;
}
-
+
// Make sure a navigate doesn't happen during the idle -- it can cause mMediaSource to get destroyed, which can cause a crash.
setNavigateSuspended(true);
-
+
mMediaSource->idle();
setNavigateSuspended(false);
@@ -2807,7 +2897,7 @@ void LLViewerMediaImpl::update()
{
return;
}
-
+
if(mMediaSource->isPluginExited())
{
resetPreviousMediaState();
@@ -2819,18 +2909,18 @@ void LLViewerMediaImpl::update()
{
return;
}
-
+
if(mSuspendUpdates || !mVisible)
{
return;
}
-
+
LLViewerMediaTexture* placeholder_image = updatePlaceholderImage();
-
+
if(placeholder_image)
{
LLRect dirty_rect;
-
+
// Since we're updating this texture, we know it's playing. Tell the texture to do its replacement magic so it gets rendered.
placeholder_image->setPlaying(TRUE);
@@ -2841,7 +2931,7 @@ void LLViewerMediaImpl::update()
S32 y_pos = llmax(dirty_rect.mBottom, 0);
S32 width = llmin(dirty_rect.mRight, placeholder_image->getWidth()) - x_pos;
S32 height = llmin(dirty_rect.mTop, placeholder_image->getHeight()) - y_pos;
-
+
if(width > 0 && height > 0)
{
@@ -2854,21 +2944,21 @@ void LLViewerMediaImpl::update()
// Offset the pixels pointer to match x_pos and y_pos
data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() );
data += ( y_pos * mMediaSource->getTextureDepth() );
-
+
{
LL_RECORD_BLOCK_TIME(FTM_MEDIA_SET_SUBIMAGE);
placeholder_image->setSubImage(
- data,
- mMediaSource->getBitsWidth(),
+ data,
+ mMediaSource->getBitsWidth(),
mMediaSource->getBitsHeight(),
- x_pos,
- y_pos,
- width,
+ x_pos,
+ y_pos,
+ width,
height);
}
}
-
+
mMediaSource->resetDirty();
}
}
@@ -2889,10 +2979,10 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage()
// The code that created this instance will read from the plugin's bits.
return NULL;
}
-
+
LLViewerMediaTexture* placeholder_image = LLViewerTextureManager::getMediaTexture( mTextureId );
-
- if (mNeedsNewTexture
+
+ if (mNeedsNewTexture
|| placeholder_image->getUseMipMaps()
|| (placeholder_image->getWidth() != mMediaSource->getTextureWidth())
|| (placeholder_image->getHeight() != mMediaSource->getTextureHeight())
@@ -2906,7 +2996,7 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage()
int texture_width = mMediaSource->getTextureWidth();
int texture_height = mMediaSource->getTextureHeight();
int texture_depth = mMediaSource->getTextureDepth();
-
+
// MEDIAOPT: check to see if size actually changed before doing work
placeholder_image->destroyGLTexture();
// MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work?
@@ -2932,13 +3022,13 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage()
// FIXME
// placeholder_image->mIsMediaTexture = true;
mNeedsNewTexture = false;
-
- // If the amount of the texture being drawn by the media goes down in either width or height,
+
+ // If the amount of the texture being drawn by the media goes down in either width or height,
// recreate the texture to avoid leaving parts of the old image behind.
mTextureUsedWidth = mMediaSource->getWidth();
mTextureUsedHeight = mMediaSource->getHeight();
}
-
+
return placeholder_image;
}
@@ -2953,14 +3043,14 @@ LLUUID LLViewerMediaImpl::getMediaTextureID() const
void LLViewerMediaImpl::setVisible(bool visible)
{
mVisible = visible;
-
+
if(mVisible)
{
if(mMediaSource && mMediaSource->isPluginExited())
{
destroyMediaSource();
}
-
+
if(!mMediaSource)
{
createMediaSource();
@@ -2994,12 +3084,12 @@ void LLViewerMediaImpl::scaleMouse(S32 *mouse_x, S32 *mouse_y)
bool LLViewerMediaImpl::isMediaTimeBased()
{
bool result = false;
-
+
if(mMediaSource)
{
result = mMediaSource->pluginSupportsMediaTime();
}
-
+
return result;
}
@@ -3007,14 +3097,14 @@ bool LLViewerMediaImpl::isMediaTimeBased()
bool LLViewerMediaImpl::isMediaPlaying()
{
bool result = false;
-
+
if(mMediaSource)
{
EMediaStatus status = mMediaSource->getStatus();
if(status == MEDIA_PLAYING || status == MEDIA_LOADING)
result = true;
}
-
+
return result;
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -3027,7 +3117,7 @@ bool LLViewerMediaImpl::isMediaPaused()
if(mMediaSource->getStatus() == MEDIA_PAUSED)
result = true;
}
-
+
return result;
}
@@ -3055,7 +3145,7 @@ void LLViewerMediaImpl::setDisabled(bool disabled, bool forcePlayOnEnable)
{
// Only do this on actual state transitions.
mIsDisabled = disabled;
-
+
if(mIsDisabled)
{
// We just disabled this media. Clear all state.
@@ -3081,13 +3171,13 @@ bool LLViewerMediaImpl::isForcedUnloaded() const
{
return true;
}
-
+
// If this media's class is not supposed to be shown, unload
if (!shouldShowBasedOnClass())
{
return true;
}
-
+
return false;
}
@@ -3100,19 +3190,19 @@ bool LLViewerMediaImpl::isPlayable() const
// All of the forced-unloaded criteria also imply not playable.
return false;
}
-
+
if(hasMedia())
{
// Anything that's already playing is, by definition, playable.
return true;
}
-
+
if(!mMediaURL.empty())
{
// If something has navigated the instance, it's ready to be played.
return true;
}
-
+
return false;
}
@@ -3124,7 +3214,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
{
case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
{
- LL_DEBUGS("Media") << "MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is: " << plugin->getClickURL() << LL_ENDL;
+ LL_DEBUGS("Media") << "MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is: " << plugin->getClickURL() << LL_ENDL;
std::string url = plugin->getClickURL();
std::string nav_type = plugin->getClickNavType();
LLURLDispatcher::dispatch(url, nav_type, NULL, mTrustedBrowser);
@@ -3143,7 +3233,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
// Reset the last known state of the media to defaults.
resetPreviousMediaState();
-
+
// TODO: may want a different message for this case?
LLSD args;
args["PLUGIN"] = LLMIMETypes::implType(mCurrentMimeType);
@@ -3165,13 +3255,13 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
//LLNotificationsUtil::add("MediaPluginFailed", args);
}
break;
-
+
case MEDIA_EVENT_CURSOR_CHANGED:
{
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << plugin->getCursorName() << LL_ENDL;
std::string cursor = plugin->getCursorName();
-
+
if(cursor == "arrow")
mLastSetCursor = UI_CURSOR_ARROW;
else if(cursor == "ibeam")
@@ -3187,6 +3277,13 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
}
break;
+ case LLViewerMediaObserver::MEDIA_EVENT_FILE_DOWNLOAD:
+ {
+ //llinfos << "Media event - file download requested - filename is " << self->getFileDownloadFilename() << llendl;
+ LLNotificationsUtil::add("MediaFileDownloadUnsupported");
+ }
+ break;
+
case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_BEGIN:
{
LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_BEGIN, uri is: " << plugin->getNavigateURI() << LL_ENDL;
@@ -3232,7 +3329,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
}
}
break;
-
+
case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED:
{
LL_DEBUGS("Media") << "MEDIA_EVENT_LOCATION_CHANGED, uri is: " << plugin->getLocation() << LL_ENDL;
@@ -3269,15 +3366,15 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
{
// Display a file picker
std::string response;
-
+
LLFilePicker& picker = LLFilePicker::instance();
if (!picker.getOpenFile(LLFilePicker::FFLOAD_ALL))
{
// The user didn't pick a file -- the empty response string will indicate this.
}
-
+
response = picker.getFirstFile();
-
+
plugin->sendPickFileResponse(response);
}
break;
@@ -3433,7 +3530,7 @@ void LLViewerMediaImpl::calculateInterest()
{
LL_RECORD_BLOCK_TIME(FTM_MEDIA_CALCULATE_INTEREST);
LLViewerMediaTexture* texture = LLViewerTextureManager::findMediaTexture( mTextureId );
-
+
if(texture != NULL)
{
mInterest = texture->getMaxVirtualSize();
@@ -3443,7 +3540,7 @@ void LLViewerMediaImpl::calculateInterest()
// This will be a relatively common case now, since it will always be true for unloaded media.
mInterest = 0.0f;
}
-
+
// Calculate distance from the avatar, for use in the proximity calculation.
mProximityDistance = 0.0f;
mProximityCamera = 0.0f;
@@ -3453,7 +3550,7 @@ void LLViewerMediaImpl::calculateInterest()
std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
LLVOVolume* objp = *iter ;
llassert_always(objp != NULL) ;
-
+
// The distance calculation is invalid for HUD attachments -- leave both mProximityDistance and mProximityCamera at 0 for them.
if(!objp->isHUDAttachment())
{
@@ -3466,12 +3563,12 @@ void LLViewerMediaImpl::calculateInterest()
mProximityCamera = camera_delta.magVec();
}
}
-
+
if(mNeedsMuteCheck)
{
// Check all objects this instance is associated with, and those objects' owners, against the mute list
mIsMuted = false;
-
+
std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
for(; iter != mObjectList.end() ; ++iter)
{
@@ -3498,7 +3595,7 @@ void LLViewerMediaImpl::calculateInterest()
}
}
}
-
+
mNeedsMuteCheck = false;
}
}
@@ -3506,7 +3603,7 @@ void LLViewerMediaImpl::calculateInterest()
F64 LLViewerMediaImpl::getApproximateTextureInterest()
{
F64 result = 0.0f;
-
+
if(mMediaSource)
{
result = mMediaSource->getFullWidth();
@@ -3524,8 +3621,8 @@ F64 LLViewerMediaImpl::getApproximateTextureInterest()
void LLViewerMediaImpl::setUsedInUI(bool used_in_ui)
{
- mUsedInUI = used_in_ui;
-
+ mUsedInUI = used_in_ui;
+
// HACK: Force elements used in UI to load right away.
// This fixes some issues where UI code that uses the browser instance doesn't expect it to be unloaded.
if(mUsedInUI && (mPriority == LLPluginClassMedia::PRIORITY_UNLOADED))
@@ -3545,7 +3642,7 @@ void LLViewerMediaImpl::setUsedInUI(bool used_in_ui)
void LLViewerMediaImpl::setBackgroundColor(LLColor4 color)
{
- mBackgroundColor = color;
+ mBackgroundColor = color;
if(mMediaSource)
{
@@ -3556,12 +3653,12 @@ void LLViewerMediaImpl::setBackgroundColor(LLColor4 color)
F64 LLViewerMediaImpl::getCPUUsage() const
{
F64 result = 0.0f;
-
+
if(mMediaSource)
{
result = mMediaSource->getCPUUsage();
}
-
+
return result;
}
@@ -3575,19 +3672,19 @@ void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority)
<< " to " << LLPluginClassMedia::priorityToString(priority)
<< LL_ENDL;
}
-
+
mPriority = priority;
-
+
if(priority == LLPluginClassMedia::PRIORITY_UNLOADED)
{
if(mMediaSource)
{
// Need to unload the media source
-
+
// First, save off previous media state
mPreviousMediaState = mMediaSource->getStatus();
mPreviousMediaTime = mMediaSource->getCurrentTime();
-
+
destroyMediaSource();
}
}
@@ -3596,7 +3693,7 @@ void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority)
{
mMediaSource->setPriority(mPriority);
}
-
+
// NOTE: loading (or reloading) media sources whose priority has risen above PRIORITY_UNLOADED is done in update().
}
@@ -3611,8 +3708,8 @@ void LLViewerMediaImpl::setLowPrioritySizeLimit(int size)
void LLViewerMediaImpl::setNavState(EMediaNavState state)
{
mMediaNavState = state;
-
- switch (state)
+
+ switch (state)
{
case MEDIANAVSTATE_NONE: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_NONE" << LL_ENDL; break;
case MEDIANAVSTATE_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_BEGUN" << LL_ENDL; break;
@@ -3650,9 +3747,10 @@ void LLViewerMediaImpl::cancelMimeTypeProbe()
if (probeAdapter)
probeAdapter->cancelSuspendedOperation();
+
}
-void LLViewerMediaImpl::addObject(LLVOVolume* obj)
+void LLViewerMediaImpl::addObject(LLVOVolume* obj)
{
std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
for(; iter != mObjectList.end() ; ++iter)
@@ -3666,14 +3764,14 @@ void LLViewerMediaImpl::addObject(LLVOVolume* obj)
mObjectList.push_back(obj) ;
mNeedsMuteCheck = true;
}
-
-void LLViewerMediaImpl::removeObject(LLVOVolume* obj)
+
+void LLViewerMediaImpl::removeObject(LLVOVolume* obj)
{
- mObjectList.remove(obj) ;
+ mObjectList.remove(obj) ;
mNeedsMuteCheck = true;
}
-
-const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const
+
+const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const
{
return &mObjectList ;
}
@@ -3681,13 +3779,13 @@ const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const
LLVOVolume *LLViewerMediaImpl::getSomeObject()
{
LLVOVolume *result = NULL;
-
+
std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
if(iter != mObjectList.end())
{
result = *iter;
}
-
+
return result;
}
@@ -3700,12 +3798,12 @@ void LLViewerMediaImpl::setTextureID(LLUUID id)
// Remove this item's entry from the map
sViewerMediaTextureIDMap.erase(mTextureId);
}
-
+
if(id.notNull())
{
sViewerMediaTextureIDMap.insert(LLViewerMedia::impl_id_map::value_type(id, this));
}
-
+
mTextureId = id;
}
}
@@ -3714,7 +3812,7 @@ void LLViewerMediaImpl::setTextureID(LLUUID id)
//
bool LLViewerMediaImpl::isAutoPlayable() const
{
- return (mMediaAutoPlay &&
+ return (mMediaAutoPlay &&
gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
gSavedSettings.getBOOL("MediaTentativeAutoPlay"));
}
@@ -3725,20 +3823,20 @@ bool LLViewerMediaImpl::shouldShowBasedOnClass() const
{
// If this is parcel media or in the UI, return true always
if (getUsedInUI() || isParcelMedia()) return true;
-
+
bool attached_to_another_avatar = isAttachedToAnotherAvatar();
bool inside_parcel = isInAgentParcel();
-
+
// LL_INFOS() << " hasFocus = " << hasFocus() <<
// " others = " << (attached_to_another_avatar && gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING)) <<
// " within = " << (inside_parcel && gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING)) <<
// " outside = " << (!inside_parcel && gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING)) << LL_ENDL;
-
+
// If it has focus, we should show it
// This is incorrect, and causes EXT-6750 (disabled attachment media still plays)
// if (hasFocus())
// return true;
-
+
// If it is attached to an avatar and the pref is off, we shouldn't show it
if (attached_to_another_avatar)
{
@@ -3751,7 +3849,7 @@ bool LLViewerMediaImpl::shouldShowBasedOnClass() const
return show_media_within_parcel;
}
- else
+ else
{
static LLCachedControl<bool> show_media_outside_parcel(gSavedSettings, LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING, true);
@@ -3764,7 +3862,7 @@ bool LLViewerMediaImpl::shouldShowBasedOnClass() const
bool LLViewerMediaImpl::isAttachedToAnotherAvatar() const
{
bool result = false;
-
+
std::list< LLVOVolume* >::const_iterator iter = mObjectList.begin();
std::list< LLVOVolume* >::const_iterator end = mObjectList.end();
for ( ; iter != end; iter++)
@@ -3808,7 +3906,7 @@ bool LLViewerMediaImpl::isObjectAttachedToAnotherAvatar(LLVOVolume *obj)
bool LLViewerMediaImpl::isInAgentParcel() const
{
bool result = false;
-
+
std::list< LLVOVolume* >::const_iterator iter = mObjectList.begin();
std::list< LLVOVolume* >::const_iterator end = mObjectList.end();
for ( ; iter != end; iter++)
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index d93eb3d6e0..b92977f093 100755
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -153,7 +153,7 @@ public:
static void removeCookie(const std::string &name, const std::string &domain, const std::string &path = std::string("/") );
static void openIDSetup(const std::string &openid_url, const std::string &openid_token);
- static void openIDCookieResponse(const std::string &cookie);
+ static void openIDCookieResponse(const std::string& url, const std::string &cookie);
static void proxyWindowOpened(const std::string &target, const std::string &uuid);
static void proxyWindowClosed(const std::string &uuid);
@@ -167,7 +167,8 @@ public:
static LLCore::HttpHeaders::ptr_t getHttpHeaders();
private:
- static void setOpenIDCookie();
+ static bool parseRawCookie(const std::string raw_cookie, std::string& name, std::string& value, std::string& path, bool& httponly, bool& secure);
+ static void setOpenIDCookie(const std::string& url);
static void onTeleportFinished();
static void openIDSetupCoro(std::string openidUrl, std::string openidToken);
@@ -231,7 +232,8 @@ public:
void mouseDown(const LLVector2& texture_coords, MASK mask, S32 button = 0);
void mouseUp(const LLVector2& texture_coords, MASK mask, S32 button = 0);
void mouseMove(const LLVector2& texture_coords, MASK mask);
- void mouseDoubleClick(S32 x,S32 y, MASK mask, S32 button = 0);
+ void mouseDoubleClick(const LLVector2& texture_coords, MASK mask);
+ void mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button = 0);
void scrollWheel(S32 x, S32 y, MASK mask);
void mouseCapture();
@@ -244,6 +246,7 @@ public:
void navigateInternal();
void navigateStop();
bool handleKeyHere(KEY key, MASK mask);
+ bool handleKeyUpHere(KEY key, MASK mask);
bool handleUnicodeCharHere(llwchar uni_char);
bool canNavigateForward();
bool canNavigateBack();
diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp
index aa019dfdd8..7b4df3d3da 100755
--- a/indra/newview/llviewermediafocus.cpp
+++ b/indra/newview/llviewermediafocus.cpp
@@ -352,6 +352,18 @@ BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent)
return true;
}
+BOOL LLViewerMediaFocus::handleKeyUp(KEY key, MASK mask, BOOL called_from_parent)
+{
+ LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+ if (media_impl)
+ {
+ media_impl->handleKeyUpHere(key, mask);
+ }
+ return true;
+}
+
+
+
BOOL LLViewerMediaFocus::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
{
LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
@@ -603,3 +615,13 @@ LLUUID LLViewerMediaFocus::getControlsMediaID()
return LLUUID::null;
}
+
+bool LLViewerMediaFocus::wantsKeyUpKeyDown() const
+{
+ return true;
+}
+
+bool LLViewerMediaFocus::wantsReturnKey() const
+{
+ return true;
+}
diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h
index f03dd8751e..0b2a64868e 100755
--- a/indra/newview/llviewermediafocus.h
+++ b/indra/newview/llviewermediafocus.h
@@ -56,6 +56,7 @@ public:
/*virtual*/ bool getFocus();
/*virtual*/ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+ /*virtual*/ BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent);
/*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
@@ -87,6 +88,10 @@ public:
// Return the ID of the media instance the controls are currently attached to (either focus or hover).
LLUUID getControlsMediaID();
+ // The MoaP object wants keyup and keydown events. Overridden to return true.
+ virtual bool wantsKeyUpKeyDown() const;
+ virtual bool wantsReturnKey() const;
+
protected:
/*virtual*/ void onFocusReceived();
/*virtual*/ void onFocusLost();
diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp
index 828271da7a..0ab3d2b4e7 100755
--- a/indra/newview/llviewerparcelmedia.cpp
+++ b/indra/newview/llviewerparcelmedia.cpp
@@ -594,7 +594,13 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PICK_FILE_REQUEST" << LL_ENDL;
}
break;
-
+
+ case MEDIA_EVENT_FILE_DOWNLOAD:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_FILE_DOWNLOAD" << LL_ENDL;
+ }
+ break;
+
case MEDIA_EVENT_GEOMETRY_CHANGE:
{
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID() << LL_ENDL;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index ba84d7aa2c..4d1cacca1f 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1381,7 +1381,11 @@ BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated)
// it's all entered/processed.
if (key == KEY_RETURN && mask == MASK_NONE)
{
- return FALSE;
+ // RIDER: although, at times some of the controlls (in particular the CEF viewer
+ // would like to know about the KEYDOWN for an enter key... so ask and pass it along.
+ LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
+ if (keyboard_focus && !keyboard_focus->wantsReturnKey())
+ return FALSE;
}
return gViewerKeyboard.handleKey(key, mask, repeated);
@@ -1399,10 +1403,9 @@ BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key, MASK mask)
tool_inspectp->keyUp(key, mask);
}
- return FALSE;
+ return gViewerKeyboard.handleKeyUp(key, mask);
}
-
void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
{
LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);
@@ -2019,6 +2022,7 @@ void LLViewerWindow::initWorldUI()
}
gHUDView = new LLHUDView(hud_rect);
getRootView()->addChild(gHUDView);
+ getRootView()->sendChildToBack(gHUDView);
}
LLPanel* panel_ssf_container = getRootView()->getChild<LLPanel>("state_management_buttons_container");
@@ -2544,21 +2548,67 @@ void LLViewerWindow::draw()
//#endif
}
+// Takes a single keyup event, usually when UI is visible
+BOOL LLViewerWindow::handleKeyUp(KEY key, MASK mask)
+{
+ LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
+
+ if (keyboard_focus
+ && !(mask & (MASK_CONTROL | MASK_ALT))
+ && !gFocusMgr.getKeystrokesOnly())
+ {
+ // We have keyboard focus, and it's not an accelerator
+ if (keyboard_focus && keyboard_focus->wantsKeyUpKeyDown())
+ {
+ return keyboard_focus->handleKeyUp(key, mask, FALSE);
+ }
+ else if (key < 0x80)
+ {
+ // Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first.
+ return (gFocusMgr.getKeyboardFocus() != NULL);
+ }
+ }
+
+ if (keyboard_focus)
+ {
+ if (keyboard_focus->handleKeyUp(key, mask, FALSE))
+ {
+ LL_DEBUGS() << "LLviewerWindow::handleKeyUp - in 'traverse up' - no loops seen... just called keyboard_focus->handleKeyUp an it returned true" << LL_ENDL;
+ LLViewerEventRecorder::instance().logKeyEvent(key, mask);
+ return TRUE;
+ }
+ else {
+ LL_DEBUGS() << "LLviewerWindow::handleKeyUp - in 'traverse up' - no loops seen... just called keyboard_focus->handleKeyUp an it returned FALSE" << LL_ENDL;
+ }
+ }
+
+ // don't pass keys on to world when something in ui has focus
+ return gFocusMgr.childHasKeyboardFocus(mRootView)
+ || LLMenuGL::getKeyboardMode()
+ || (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive());
+}
+
// Takes a single keydown event, usually when UI is visible
BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
{
// hide tooltips on keypress
LLToolTipMgr::instance().blockToolTips();
- if (gFocusMgr.getKeyboardFocus()
+ LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
+
+ if (keyboard_focus
&& !(mask & (MASK_CONTROL | MASK_ALT))
&& !gFocusMgr.getKeystrokesOnly())
{
// We have keyboard focus, and it's not an accelerator
- if (key < 0x80)
+ if (keyboard_focus && keyboard_focus->wantsKeyUpKeyDown())
+ {
+ return keyboard_focus->handleKey(key, mask, FALSE );
+ }
+ else if (key < 0x80)
{
// Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first.
- return (gFocusMgr.getKeyboardFocus() != NULL);
+ return (keyboard_focus != NULL);
}
}
@@ -2572,7 +2622,6 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
return TRUE;
}
- LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
// give menus a chance to handle modified (Ctrl, Alt) shortcut keys before current focus
// as long as focus isn't locked
@@ -2598,7 +2647,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
// give floaters first chance to handle TAB key
// so frontmost floater gets focus
// if nothing has focus, go to first or last UI element as appropriate
- if (key == KEY_TAB && (mask & MASK_CONTROL || gFocusMgr.getKeyboardFocus() == NULL))
+ if (key == KEY_TAB && (mask & MASK_CONTROL || keyboard_focus == NULL))
{
LL_WARNS() << "LLviewerWindow::handleKey give floaters first chance at tab key " << LL_ENDL;
if (gMenuHolder) gMenuHolder->hideMenus();
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 7fde52d4e1..17e9ac2636 100755
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -314,6 +314,7 @@ public:
LLView* getHintHolder() { return mHintHolder.get(); }
LLView* getLoginPanelHolder() { return mLoginPanelHolder.get(); }
BOOL handleKey(KEY key, MASK mask);
+ BOOL handleKeyUp(KEY key, MASK mask);
void handleScrollWheel (S32 clicks);
// add and remove views from "popup" layer
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index 0be6e49834..b37e41fb85 100755
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -234,6 +234,9 @@ std::string LLWeb::expandURLSubstitutions(const std::string &url,
//static
bool LLWeb::useExternalBrowser(const std::string &url)
{
+#ifdef EXTERNAL_TOS
+ return true;
+#else
if (gSavedSettings.getU32("PreferredBrowserBehavior") == BROWSER_EXTERNAL_ONLY)
{
return true;
@@ -250,4 +253,5 @@ bool LLWeb::useExternalBrowser(const std::string &url)
return !(boost::regex_search(uri_string, matches, pattern));
}
return false;
+#endif
}
diff --git a/indra/newview/skins/default/xui/en/floater_tos.xml b/indra/newview/skins/default/xui/en/floater_tos.xml
index af1617eb39..590d9d1844 100755
--- a/indra/newview/skins/default/xui/en/floater_tos.xml
+++ b/indra/newview/skins/default/xui/en/floater_tos.xml
@@ -57,6 +57,21 @@
width="552">
Please read the following Terms of Service and Privacy Policy carefully. To continue logging in to [SECOND_LIFE], you must accept the agreement.
</text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="30"
+ layout="topleft"
+ left="16"
+ name="external_tos_required"
+ visible="false"
+ top="32"
+ word_wrap="true"
+ width="552">
+ You will need to go to my.secondlife.com and log in to accept the Terms of Service before you can proceed. Thank you!
+ </text>
<web_browser
trusted_content="true"
follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml
index 73ca7c529d..419ec359a6 100755
--- a/indra/newview/skins/default/xui/en/menu_login.xml
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -236,7 +236,7 @@
name="Web Content Floater Debug Test">
<menu_item_call.on_click
function="Advanced.WebContentTest"
- parameter="http://google.com"/>
+ parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/>
</menu_item_call>
<menu
create_jump_keys="true"
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index f22986438c..a58fd54d4a 100755
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1431,7 +1431,7 @@
function="Floater.Show"
parameter="bumps" />
</menu_item_call>
- <menu_item_separator/>
+ <menu_item_separator/>
<menu_item_call
label="About [APP_NAME]"
name="About Second Life">
@@ -3184,7 +3184,7 @@
shortcut="control|shift|Z">
<menu_item_call.on_click
function="Advanced.WebContentTest"
- parameter="http://google.com"/>
+ parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/>
</menu_item_call>
<menu_item_call
label="FB Connect Test"
diff --git a/indra/newview/skins/default/xui/en/mime_types.xml b/indra/newview/skins/default/xui/en/mime_types.xml
index f5f2223330..7cb4a6e53b 100755
--- a/indra/newview/skins/default/xui/en/mime_types.xml
+++ b/indra/newview/skins/default/xui/en/mime_types.xml
@@ -7,7 +7,7 @@
none
</defaultwidget>
<defaultimpl>
- media_plugin_webkit
+ media_plugin_cef
</defaultimpl>
<widgetset name="web">
<label name="web_label">
@@ -141,7 +141,7 @@
none
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="none/none">
@@ -152,7 +152,7 @@
none
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="audio/*">
@@ -185,7 +185,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="video/vnd.secondlife.qt.legacy">
@@ -207,7 +207,7 @@
web
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/ogg">
@@ -229,7 +229,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/postscript">
@@ -240,7 +240,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/rtf">
@@ -251,7 +251,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/smil">
@@ -262,7 +262,7 @@
movie
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/xhtml+xml">
@@ -273,7 +273,7 @@
web
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/x-director">
@@ -284,7 +284,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="audio/mid">
@@ -339,7 +339,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="image/gif">
@@ -350,7 +350,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="image/jpeg">
@@ -361,7 +361,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="image/png">
@@ -372,7 +372,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="image/svg+xml">
@@ -383,7 +383,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="image/tiff">
@@ -394,7 +394,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="text/html">
@@ -405,7 +405,7 @@
web
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="text/plain">
@@ -416,7 +416,7 @@
text
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="text/xml">
@@ -427,7 +427,7 @@
text
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="video/mpeg">
diff --git a/indra/newview/skins/default/xui/en/mime_types_mac.xml b/indra/newview/skins/default/xui/en/mime_types_mac.xml
index 90230f12dd..f71c24b2e4 100755
--- a/indra/newview/skins/default/xui/en/mime_types_mac.xml
+++ b/indra/newview/skins/default/xui/en/mime_types_mac.xml
@@ -7,7 +7,7 @@
none
</defaultwidget>
<defaultimpl>
- media_plugin_webkit
+ media_plugin_cef
</defaultimpl>
<widgetset name="web">
<label name="web_label">
@@ -152,7 +152,7 @@
none
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="audio/*">
@@ -185,7 +185,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="video/vnd.secondlife.qt.legacy">
@@ -207,7 +207,7 @@
web
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/ogg">
@@ -229,7 +229,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/postscript">
@@ -240,7 +240,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/rtf">
@@ -251,7 +251,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/smil">
@@ -262,7 +262,7 @@
movie
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/xhtml+xml">
@@ -273,7 +273,7 @@
web
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/x-director">
@@ -284,7 +284,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="audio/mid">
@@ -339,7 +339,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="image/gif">
@@ -350,7 +350,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="image/jpeg">
@@ -361,7 +361,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="image/png">
@@ -372,7 +372,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="image/svg+xml">
@@ -383,7 +383,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="image/tiff">
@@ -394,7 +394,7 @@
image
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="text/html">
@@ -405,7 +405,7 @@
web
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="text/plain">
@@ -416,7 +416,7 @@
text
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="text/xml">
@@ -427,7 +427,7 @@
text
</widgettype>
<impl>
- media_plugin_webkit
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="video/mpeg">
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index f79e8103b6..4a1336d2b5 100755
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -1592,11 +1592,24 @@ The object may be out of range or may have been deleted.
icon="alertmodal.tga"
name="CannotDownloadFile"
type="alertmodal">
-Unable to download file
- <tag>fail</tag>
+ Unable to download file
+ <tag>fail</tag>
</notification>
<notification
+ name="MediaFileDownloadUnsupported"
+ label=""
+ type="alert">
+ <unique/>
+ <tag>confirm</tag>
+ You have requested a file download, which is not supported within [SECOND_LIFE].
+ <usetemplate
+ ignoretext="Warn about unsupported file downloads"
+ name="okignore"
+ yestext="OK"/>
+ </notification>
+
+ <notification
icon="alertmodal.tga"
name="CannotWriteFile"
type="alertmodal">
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
index b201e071ef..45b2b6ec27 100755
--- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
@@ -224,19 +224,6 @@
radio_style="false"
width="400"
top_pad="5"/>
- <check_box
- top_delta="4"
- enabled="true"
- follows="left|top"
- height="14"
- initial_value="false"
- control_name="MediaEnablePopups"
- label="Enable media browser pop-ups"
- left_delta="0"
- mouse_opaque="true"
- name="media_popup_enabled"
- width="400"
- top_pad="5"/>
<text
type="string"
length="1"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 4eb6e2462d..f2eddbb38e 100755
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -50,7 +50,7 @@ OpenGL Version: [OPENGL_VERSION]
libcurl Version: [LIBCURL_VERSION]
J2C Decoder Version: [J2C_VERSION]
Audio Driver Version: [AUDIO_DRIVER_VERSION]
-Qt Webkit Version: [QT_WEBKIT_VERSION]
+LLCEFLib/CEF Version: [LLCEFLIB_VERSION]
Voice Server Version: [VOICE_VERSION]
</string>
<string name="AboutTraffic">Packets Lost: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%)</string>
diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp
index 61120686e4..4c0acded9e 100755
--- a/indra/newview/tests/llmediadataclient_test.cpp
+++ b/indra/newview/tests/llmediadataclient_test.cpp
@@ -26,7 +26,7 @@
#include "linden_common.h"
#include "../llviewerprecompiledheaders.h"
-
+
#include <iostream>
#include "../test/lltut.h"
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index cae6bded9f..f7992dba90 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -340,9 +340,9 @@ class Windows_i686_Manifest(ViewerManifest):
self.path(src='%s/secondlife-bin.exe' % self.args['configuration'], dst=self.final_exe())
# Plugin host application
- # The current slplugin package places slplugin.exe right into the
- # packages base directory.
- self.path2basename(pkgdir, "slplugin.exe")
+ self.path2basename(os.path.join(os.pardir,
+ 'llplugin', 'slplugin', self.args['configuration']),
+ "slplugin.exe")
self.path2basename("../viewer_components/updater/scripts/windows", "update_install.bat")
# Get shared libs from the shared libs staging directory
@@ -428,54 +428,121 @@ class Windows_i686_Manifest(ViewerManifest):
self.path("featuretable_xp.txt")
# Media plugins - QuickTime
- # Media plugins - WebKit/Qt
- if self.prefix(src=os.path.join(pkgdir, "llplugin"), dst="llplugin"):
+ if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"):
self.path("media_plugin_quicktime.dll")
- self.path("media_plugin_webkit.dll")
- self.path("qtcore4.dll")
- self.path("qtgui4.dll")
- self.path("qtnetwork4.dll")
- self.path("qtopengl4.dll")
- self.path("qtwebkit4.dll")
- self.path("qtxmlpatterns4.dll")
-
- # For WebKit/Qt plugin runtimes (image format plugins)
- if self.prefix(src="imageformats", dst="imageformats"):
- self.path("qgif4.dll")
- self.path("qico4.dll")
- self.path("qjpeg4.dll")
- self.path("qmng4.dll")
- self.path("qsvg4.dll")
- self.path("qtiff4.dll")
- self.end_prefix()
-
- # For WebKit/Qt plugin runtimes (codec/character encoding plugins)
- if self.prefix(src="codecs", dst="codecs"):
- self.path("qcncodecs4.dll")
- self.path("qjpcodecs4.dll")
- self.path("qkrcodecs4.dll")
- self.path("qtwcodecs4.dll")
- self.end_prefix()
+ self.end_prefix()
- self.end_prefix()
+ # Media plugins - CEF
+ if self.prefix(src='../media_plugins/cef/%s' % self.args['configuration'], dst="llplugin"):
+ self.path("media_plugin_cef.dll")
+ self.end_prefix()
# winmm.dll shim
if self.prefix(src='../media_plugins/winmmshim/%s' % self.args['configuration'], dst=""):
self.path("winmm.dll")
self.end_prefix()
+ # CEF runtime files - debug
if self.args['configuration'].lower() == 'debug':
- if self.prefix(src=debpkgdir, dst="llplugin"):
- self.path("libeay32.dll")
- self.path("ssleay32.dll")
+ if self.prefix(src=os.path.join(os.pardir, 'packages', 'bin', 'debug'), dst="llplugin"):
+ self.path("d3dcompiler_43.dll")
+ self.path("d3dcompiler_47.dll")
+ self.path("libcef.dll")
+ self.path("libEGL.dll")
+ self.path("libGLESv2.dll")
+ self.path("llceflib_host.exe")
+ self.path("natives_blob.bin")
+ self.path("snapshot_blob.bin")
+ self.path("widevinecdmadapter.dll")
+ self.path("wow_helper.exe")
self.end_prefix()
-
else:
- if self.prefix(src=relpkgdir, dst="llplugin"):
- self.path("libeay32.dll")
- self.path("ssleay32.dll")
+ # CEF runtime files - not debug (release, relwithdebinfo etc.)
+ if self.prefix(src=os.path.join(os.pardir, 'packages', 'bin', 'release'), dst="llplugin"):
+ self.path("d3dcompiler_43.dll")
+ self.path("d3dcompiler_47.dll")
+ self.path("libcef.dll")
+ self.path("libEGL.dll")
+ self.path("libGLESv2.dll")
+ self.path("llceflib_host.exe")
+ self.path("natives_blob.bin")
+ self.path("snapshot_blob.bin")
+ self.path("widevinecdmadapter.dll")
+ self.path("wow_helper.exe")
self.end_prefix()
+ # MSVC DLLs needed for CEF and have to be in same directory as plugin
+ if self.prefix(src=os.path.join(os.pardir, 'sharedlibs', 'Release'), dst="llplugin"):
+ self.path("msvcp120.dll")
+ self.path("msvcr120.dll")
+ self.end_prefix()
+
+ # CEF files common to all configurations
+ if self.prefix(src=os.path.join(os.pardir, 'packages', 'resources'), dst="llplugin"):
+ self.path("cef.pak")
+ self.path("cef_100_percent.pak")
+ self.path("cef_200_percent.pak")
+ self.path("cef_extensions.pak")
+ self.path("devtools_resources.pak")
+ self.path("icudtl.dat")
+ self.end_prefix()
+
+ if self.prefix(src=os.path.join(os.pardir, 'packages', 'resources', 'locales'), dst=os.path.join('llplugin', 'locales')):
+ self.path("am.pak")
+ self.path("ar.pak")
+ self.path("bg.pak")
+ self.path("bn.pak")
+ self.path("ca.pak")
+ self.path("cs.pak")
+ self.path("da.pak")
+ self.path("de.pak")
+ self.path("el.pak")
+ self.path("en-GB.pak")
+ self.path("en-US.pak")
+ self.path("es-419.pak")
+ self.path("es.pak")
+ self.path("et.pak")
+ self.path("fa.pak")
+ self.path("fi.pak")
+ self.path("fil.pak")
+ self.path("fr.pak")
+ self.path("gu.pak")
+ self.path("he.pak")
+ self.path("hi.pak")
+ self.path("hr.pak")
+ self.path("hu.pak")
+ self.path("id.pak")
+ self.path("it.pak")
+ self.path("ja.pak")
+ self.path("kn.pak")
+ self.path("ko.pak")
+ self.path("lt.pak")
+ self.path("lv.pak")
+ self.path("ml.pak")
+ self.path("mr.pak")
+ self.path("ms.pak")
+ self.path("nb.pak")
+ self.path("nl.pak")
+ self.path("pl.pak")
+ self.path("pt-BR.pak")
+ self.path("pt-PT.pak")
+ self.path("ro.pak")
+ self.path("ru.pak")
+ self.path("sk.pak")
+ self.path("sl.pak")
+ self.path("sr.pak")
+ self.path("sv.pak")
+ self.path("sw.pak")
+ self.path("ta.pak")
+ self.path("te.pak")
+ self.path("th.pak")
+ self.path("tr.pak")
+ self.path("uk.pak")
+ self.path("vi.pak")
+ self.path("zh-CN.pak")
+ self.path("zh-TW.pak")
+ self.end_prefix()
+
# pull in the crash logger and updater from other projects
# tag:"crash-logger" here as a cue to the exporter
self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'],
@@ -739,14 +806,13 @@ class Darwin_i386_Manifest(ViewerManifest):
dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile)
# our apps
- for app_bld_dir, app in ((os.path.join(os.pardir,
- "mac_crash_logger",
- self.args['configuration']),
- "mac-crash-logger.app"),
+ for app_bld_dir, app in (("mac_crash_logger", "mac-crash-logger.app"),
# plugin launcher
- (pkgdir, "SLPlugin.app"),
+ (os.path.join("llplugin", "slplugin"), "SLPlugin.app"),
):
- self.path2basename(app_bld_dir, app)
+ self.path2basename(os.path.join(os.pardir,
+ app_bld_dir, self.args['configuration']),
+ app)
# our apps dependencies on shared libs
# for each app, for each dylib we collected in dylibs,
@@ -759,46 +825,57 @@ class Darwin_i386_Manifest(ViewerManifest):
symlinkf(src, dst)
except OSError as err:
print "Can't symlink %s -> %s: %s" % (src, dst, err)
- # SLPlugin.app/Contents/Resources gets those Qt4 libraries it needs.
- if self.prefix(src="", dst="SLPlugin.app/Contents/Resources"):
- for libfile in ('libQtCore.4.dylib',
- 'libQtCore.4.7.1.dylib',
- 'libQtGui.4.dylib',
- 'libQtGui.4.7.1.dylib',
- 'libQtNetwork.4.dylib',
- 'libQtNetwork.4.7.1.dylib',
- 'libQtOpenGL.4.dylib',
- 'libQtOpenGL.4.7.1.dylib',
- 'libQtSvg.4.dylib',
- 'libQtSvg.4.7.1.dylib',
- 'libQtWebKit.4.dylib',
- 'libQtWebKit.4.7.1.dylib',
- 'libQtXml.4.dylib',
- 'libQtXml.4.7.1.dylib'):
- self.path2basename(relpkgdir, libfile)
- self.end_prefix("SLPlugin.app/Contents/Resources")
-
- # Qt4 codecs go to llplugin. Not certain why but this is the first
- # location probed according to dtruss so we'll go with that.
- if self.prefix(src=os.path.join(pkgdir, "llplugin/codecs/"), dst="llplugin/codecs"):
- self.path("libq*.dylib")
- self.end_prefix("llplugin/codecs")
-
- # Similarly for imageformats.
- if self.prefix(src=os.path.join(pkgdir, "llplugin/imageformats/"), dst="llplugin/imageformats"):
- self.path("libq*.dylib")
- self.end_prefix("llplugin/imageformats")
-
- # SLPlugin plugins proper
- if self.prefix(src=os.path.join(pkgdir, "llplugin"), dst="llplugin"):
- self.path("media_plugin_quicktime.dylib")
- self.path("media_plugin_webkit.dylib")
+
+ # LLCefLib helper apps go inside SLPlugin.app
+ if self.prefix(src="", dst="SLPlugin.app/Contents/Frameworks"):
+ for helperappfile in ('LLCefLib Helper.app',
+ 'LLCefLib Helper EH.app'):
+ self.path2basename(relpkgdir, helperappfile)
+
+ pluginframeworkpath = self.dst_path_of('Chromium Embedded Framework.framework');
+
+ self.end_prefix()
+
+ # SLPlugin plugins
+ if self.prefix(src="", dst="llplugin"):
+ self.path2basename("../media_plugins/quicktime/" + self.args['configuration'],
+ "media_plugin_quicktime.dylib")
+ self.path2basename("../media_plugins/cef/" + self.args['configuration'],
+ "media_plugin_cef.dylib")
self.end_prefix("llplugin")
self.end_prefix("Resources")
+ # CEF framework goes inside Second Life.app/Contents/Frameworks
+ if self.prefix(src="", dst="Frameworks"):
+ frameworkfile="Chromium Embedded Framework.framework"
+ self.path2basename(relpkgdir, frameworkfile)
+ self.end_prefix("Frameworks")
+
+ # This code constructs a relative path from the
+ # target framework folder back to the location of the symlink.
+ # It needs to be relative so that the symlink still works when
+ # (as is normal) the user moves the app bunlde out of the DMG
+ # and into the /Applications folder. Note we also call 'raise'
+ # to terminate the process if we get an error since without
+ # this symlink, Second Life web media can't possibly work.
+ # Real Framework folder:
+ # Second Life.app/Contents/Frameworks/Chromium Embedded Framework.framework/
+ # Location of symlink and why it'ds relavie
+ # Second Life.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/Chromium Embedded Framework.framework/
+ frameworkpath = os.path.join(os.pardir, os.pardir, os.pardir, os.pardir, "Frameworks", "Chromium Embedded Framework.framework")
+ try:
+ symlinkf(frameworkpath, pluginframeworkpath)
+ except OSError as err:
+ print "Can't symlink %s -> %s: %s" % (frameworkpath, pluginframeworkpath, err)
+ raise
+
self.end_prefix("Contents")
+ # fix up media_plugin.dylib so it knows where to look for CEF files it needs
+ self.run_command('install_name_tool -change "@executable_path/Chromium Embedded Framework" "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "%(config)s/Second Life.app/Contents/Resources/llplugin/media_plugin_cef.dylib"' %
+ { 'config' : self.args['configuration'] })
+
# NOTE: the -S argument to strip causes it to keep enough info for
# annotated backtraces (i.e. function names in the crash log). 'strip' with no
# arguments yields a slightly smaller binary but makes crash logs mostly useless.
@@ -808,7 +885,6 @@ class Darwin_i386_Manifest(ViewerManifest):
self.run_command('strip -S %(viewer_binary)r' %
{ 'viewer_binary' : self.dst_path_of('Contents/MacOS/Second Life')})
-
def copy_finish(self):
# Force executable permissions to be set for scripts
# see CHOP-223 and http://mercurial.selenic.com/bts/issue1802
@@ -985,7 +1061,7 @@ class LinuxManifest(ViewerManifest):
if self.prefix(src="", dst="bin"):
self.path("secondlife-bin","do-not-directly-run-secondlife-bin")
self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin")
- self.path2basename(pkgdir, "SLPlugin")
+ self.path2basename("../llplugin/slplugin", "SLPlugin")
self.path2basename("../viewer_components/updater/scripts/linux", "update_install")
self.end_prefix("bin")
@@ -1005,9 +1081,8 @@ class LinuxManifest(ViewerManifest):
self.end_prefix(icon_path)
# plugins
- if self.prefix(src=os.path.join(pkgdir, "llplugin"), dst="bin/llplugin"):
- self.path("libmedia_plugin_webkit.so")
- self.path("libmedia_plugin_gstreamer.so")
+ if self.prefix(src="", dst="bin/llplugin"):
+ self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so")
self.end_prefix("bin/llplugin")
# llcommon
@@ -1147,37 +1222,6 @@ class Linux_i686_Manifest(LinuxManifest):
self.path("libvivoxplatform.so")
self.end_prefix("lib")
- # plugin runtime
- if self.prefix(src=os.path.join(pkgdir, "lib"), dst="lib"):
- self.path("libQtCore.so*")
- self.path("libQtGui.so*")
- self.path("libQtNetwork.so*")
- self.path("libQtOpenGL.so*")
- self.path("libQtSvg.so*")
- self.path("libQtWebKit.so*")
- self.path("libQtXml.so*")
- self.end_prefix("lib")
-
- # For WebKit/Qt plugin runtimes (image format plugins)
- if self.prefix(src=os.path.join(pkgdir, "llplugin", "imageformats"),
- dst="bin/llplugin/imageformats"):
- self.path("libqgif.so")
- self.path("libqico.so")
- self.path("libqjpeg.so")
- self.path("libqmng.so")
- self.path("libqsvg.so")
- self.path("libqtiff.so")
- self.end_prefix("bin/llplugin/imageformats")
-
- # For WebKit/Qt plugin runtimes (codec/character encoding plugins)
- if self.prefix(src=os.path.join(pkgdir, "llplugin", "codecs"),
- dst="bin/llplugin/codecs"):
- self.path("libqcncodecs.so")
- self.path("libqjpcodecs.so")
- self.path("libqkrcodecs.so")
- self.path("libqtwcodecs.so")
- self.end_prefix("bin/llplugin/codecs")
-
self.strip_binaries()
diff --git a/indra/test_apps/llfbconnecttest/CMakeLists.txt b/indra/test_apps/llfbconnecttest/CMakeLists.txt
deleted file mode 100644
index 25aaebb783..0000000000
--- a/indra/test_apps/llfbconnecttest/CMakeLists.txt
+++ /dev/null
@@ -1,372 +0,0 @@
-# -*- cmake -*-
-project(llfbconnecttest)
-
-include(00-Common)
-include(FindOpenGL)
-include(LLCommon)
-include(LLPlugin)
-include(Linking)
-include(LLSharedLibs)
-include(PluginAPI)
-include(LLImage)
-include(LLMath)
-include(LLMessage)
-include(LLRender)
-include(LLWindow)
-include(Glut)
-include(Glui)
-
-include_directories(
- ${LLPLUGIN_INCLUDE_DIRS}
- ${LLCOMMON_INCLUDE_DIRS}
- ${LLIMAGE_INCLUDE_DIRS}
- ${LLMATH_INCLUDE_DIRS}
- ${LLMESSAGE_INCLUDE_DIRS}
- ${LLRENDER_INCLUDE_DIRS}
- ${LLWINDOW_INCLUDE_DIRS}
-)
-
-if (DARWIN)
- include(CMakeFindFrameworks)
- find_library(COREFOUNDATION_LIBRARY CoreFoundation)
-endif (DARWIN)
-
-### llfbconnecttest
-
-set(llfbconnecttest_SOURCE_FILES
- llfbconnecttest.cpp
- llfbconnecttest.h
- bookmarks.txt
- )
-
-add_executable(llfbconnecttest
- WIN32
- MACOSX_BUNDLE
- ${llfbconnecttest_SOURCE_FILES}
-)
-
-set_target_properties(llfbconnecttest
- PROPERTIES
- WIN32_EXECUTABLE
- FALSE
-)
-
-target_link_libraries(llfbconnecttest
- ${GLUT_LIBRARY}
- ${GLUI_LIBRARY}
- ${OPENGL_LIBRARIES}
- ${LLPLUGIN_LIBRARIES}
- ${LLMESSAGE_LIBRARIES}
- ${LLCOMMON_LIBRARIES}
- ${PLUGIN_API_WINDOWS_LIBRARIES}
-)
-
-if (DARWIN)
- # The testbed needs to use a couple of CoreFoundation calls now, to deal with being a bundled app.
- target_link_libraries(llfbconnecttest
- ${COREFOUNDATION_LIBRARY}
- )
-endif (DARWIN)
-
-add_dependencies(llfbconnecttest
- stage_third_party_libs
- SLPlugin
- media_plugin_webkit
- ${LLPLUGIN_LIBRARIES}
- ${LLMESSAGE_LIBRARIES}
- ${LLCOMMON_LIBRARIES}
-)
-
-# turn off weird GLUI pragma
-add_definitions(-DGLUI_NO_LIB_PRAGMA)
-
-if (DARWIN OR LINUX)
- # glui.h contains code that triggers the "overloaded-virtual" warning in gcc.
- set_source_files_properties(llfbconnecttest.cpp PROPERTIES COMPILE_FLAGS "-Wno-overloaded-virtual")
-endif (DARWIN OR LINUX)
-
-# Gather build products of the various dependencies into the build directory for the testbed.
-
-if (DARWIN)
- # path inside the app bundle where we'll need to copy plugins and other related files
- set(PLUGINS_DESTINATION_DIR
- ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llfbconnecttest.app/Contents/Resources
- )
-
- # create the Contents/Resources directory
- add_custom_command(
- TARGET llfbconnecttest POST_BUILD
- COMMAND ${CMAKE_COMMAND}
- ARGS
- -E
- make_directory
- ${PLUGINS_DESTINATION_DIR}
- COMMENT "Creating Resources directory in app bundle."
- )
-else (DARWIN)
- set(PLUGINS_DESTINATION_DIR
- ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
- )
-endif (DARWIN)
-
-set(BUILT_SLPLUGIN $<TARGET_FILE:SLPlugin>)
-add_custom_command(TARGET llfbconnecttest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_SLPLUGIN} ${PLUGINS_DESTINATION_DIR}
- DEPENDS ${BUILT_SLPLUGIN}
-)
-
-set(BUILT_LLCOMMON $<TARGET_FILE:llcommon>)
-add_custom_command(TARGET llfbconnecttest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_LLCOMMON} ${PLUGINS_DESTINATION_DIR}
- DEPENDS ${BUILT_LLCOMMON}
-)
-
-
-set(BUILT_WEBKIT_PLUGIN $<TARGET_FILE:media_plugin_webkit>)
-add_custom_command(TARGET llfbconnecttest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_WEBKIT_PLUGIN} ${PLUGINS_DESTINATION_DIR}
- DEPENDS ${BUILT_WEBKIT_PLUGIN}
-)
-
-# copy over bookmarks file if llfbconnecttest gets built
-set(BUILT_LLFBCONNECTTEST $<TARGET_FILE:llfbconnecttest>)
-add_custom_command(TARGET llfbconnecttest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${CMAKE_CURRENT_BINARY_DIR}/
- DEPENDS ${BUILT_LLFBCONNECTTEST}
-)
-
-# also copy it to the same place as SLPlugin, which is what the mac wants...
-add_custom_command(TARGET llfbconnecttest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${PLUGINS_DESTINATION_DIR}
- DEPENDS ${BUILT_LLFBCONNECTTEST}
-)
-
-if(WINDOWS)
- #********************
- # Plugin test library deploy
- #
- # Debug config runtime files required for the FB connect test
- set(fbconnecttest_debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}")
- set(fbconnecttest_debug_files
- libeay32.dll
- libglib-2.0-0.dll
- libgmodule-2.0-0.dll
- libgobject-2.0-0.dll
- libgthread-2.0-0.dll
- qtcored4.dll
- qtguid4.dll
- qtnetworkd4.dll
- qtopengld4.dll
- qtwebkitd4.dll
- ssleay32.dll
- )
- copy_if_different(
- ${fbconnecttest_debug_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/Debug"
- out_targets
- ${fbconnecttest_debug_files}
- )
- set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
-
- # Debug config runtime files required for the FB connect test (Qt image format plugins)
- set(fbconecttest_debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}/imageformats")
- set(fbconecttest_debug_files
- qgifd4.dll
- qicod4.dll
- qjpegd4.dll
- qmngd4.dll
- qsvgd4.dll
- qtiffd4.dll
- )
- copy_if_different(
- ${fbconecttest_debug_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/Debug/imageformats"
- out_targets
- ${fbconecttest_debug_files}
- )
- set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
-
- # Debug config runtime files required for the FB connect test (Qt codec plugins)
- set(fbconnecttest_debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}/codecs")
- set(fbconnecttest_debug_files
- qcncodecsd4.dll
- qjpcodecsd4.dll
- qkrcodecsd4.dll
- qtwcodecsd4.dll
- )
- copy_if_different(
- ${fbconnecttest_debug_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/Debug/codecs"
- out_targets
- ${fbconnecttest_debug_files}
- )
- set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
-
- # Release & ReleaseDebInfo config runtime files required for the FB connect test
- set(fbconnecttest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
- set(fbconnecttest_release_files
- libeay32.dll
- libglib-2.0-0.dll
- libgmodule-2.0-0.dll
- libgobject-2.0-0.dll
- libgthread-2.0-0.dll
- qtcore4.dll
- qtgui4.dll
- qtnetwork4.dll
- qtopengl4.dll
- qtwebkit4.dll
- qtxmlpatterns4.dll
- ssleay32.dll
- )
- copy_if_different(
- ${fbconnecttest_release_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/Release"
- out_targets
- ${fbconnecttest_release_files}
- )
- set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
-
- copy_if_different(
- ${fbconnecttest_release_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo"
- out_targets
- ${fbconnecttest_release_files}
- )
- set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
-
- # Release & ReleaseDebInfo config runtime files required for the FB connect test (Qt image format plugins)
- set(fbconnecttest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}/imageformats")
- set(fbconnecttest_release_files
- qgif4.dll
- qico4.dll
- qjpeg4.dll
- qmng4.dll
- qsvg4.dll
- qtiff4.dll
- )
- copy_if_different(
- ${fbconnecttest_release_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/Release/imageformats"
- out_targets
- ${fbconnecttest_release_files}
- )
- set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
-
- copy_if_different(
- ${fbconnecttest_release_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/imageformats"
- out_targets
- ${fbconnecttest_release_files}
- )
- set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
-
- # Release & ReleaseDebInfo config runtime files required for the FB connect test (Qt codec plugins)
- set(fbconnecttest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}/codecs")
- set(fbconnecttest_release_files
- qcncodecs4.dll
- qjpcodecs4.dll
- qkrcodecs4.dll
- qtwcodecs4.dll
- )
- copy_if_different(
- ${fbconnecttest_release_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/Release/codecs"
- out_targets
- ${fbconnecttest_release_files}
- )
- set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
-
- copy_if_different(
- ${fbconnecttest_release_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/codecs"
- out_targets
- ${fbconnecttest_release_files}
- )
- set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
-
- add_custom_target(copy_fbconnecttest_libs ALL
- DEPENDS
- ${fbconnect_test_targets}
- )
-
- add_dependencies(llfbconnecttest copy_fbconnecttest_libs)
-
-endif(WINDOWS)
-
-if (DARWIN)
- set(fbconnecttest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
- set(fbconnecttest_release_files
- libexception_handler.dylib
- libaprutil-1.0.dylib
- libapr-1.0.dylib
- libexpat.1.5.2.dylib
- libQtCore.4.7.1.dylib
- libQtCore.4.dylib
- libQtGui.4.7.1.dylib
- libQtGui.4.dylib
- libQtNetwork.4.7.1.dylib
- libQtNetwork.4.dylib
- libQtOpenGL.4.7.1.dylib
- libQtOpenGL.4.dylib
- libQtWebKit.4.7.1.dylib
- libQtWebKit.4.dylib
- libQtSvg.4.7.1.dylib
- libQtSvg.4.dylib
- libQtXml.4.7.1.dylib
- libQtXml.4.dylib
- )
- copy_if_different(
- ${fbconnecttest_release_src_dir}
- "${PLUGINS_DESTINATION_DIR}"
- out_targets
- ${fbconnecttest_release_files}
- )
- set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
-
- # Release & ReleaseDebInfo config runtime files required for the FB connect test (Qt image format plugins)
- set(fbconnecttest_release_src_dir "${ARCH_PREBUILT_DIRS_PLUGINS}/imageformats")
- set(fbconnecttest_release_files
- libqgif.dylib
- libqico.dylib
- libqjpeg.dylib
- libqmng.dylib
- libqsvg.dylib
- libqtiff.dylib
- )
- copy_if_different(
- ${fbconnecttest_release_src_dir}
- "${PLUGINS_DESTINATION_DIR}/imageformats"
- out_targets
- ${fbconnecttest_release_files}
- )
- set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
-
- # Release & ReleaseDebInfo config runtime files required for the FB connect test (Qt codec plugins)
- set(fbconnecttest_release_src_dir "${ARCH_PREBUILT_DIRS_PLUGINS}/codecs")
- set(fbconnecttest_release_files
- libqcncodecs.dylib
- libqjpcodecs.dylib
- libqkrcodecs.dylib
- libqtwcodecs.dylib
- )
- copy_if_different(
- ${fbconnecttest_release_src_dir}
- "${PLUGINS_DESTINATION_DIR}/codecs"
- out_targets
- ${fbconnecttest_release_files}
- )
- set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
-
- add_custom_target(copy_fbconnecttest_libs ALL
- DEPENDS
- ${fbconnect_test_targets}
- )
-
- add_dependencies(llfbconnecttest copy_fbconnecttest_libs)
-endif (DARWIN)
-
-if (LINUX)
-
-endif (LINUX)
-
-ll_deploy_sharedlibs_command(llfbconnecttest)
diff --git a/indra/test_apps/llfbconnecttest/README.Linden b/indra/test_apps/llfbconnecttest/README.Linden
deleted file mode 100644
index 7488ce680a..0000000000
--- a/indra/test_apps/llfbconnecttest/README.Linden
+++ /dev/null
@@ -1,20 +0,0 @@
-
-1. Description
-
- Exercises SLPlugin. Specific functions and goals aren't clear
- from the source.
-
-2. Running
-
- 2.1 Mac
-
- Make certain '.' is included in PATH. E.g.:
-
- PATH=.:"$PATH" open build-darwin-i386/test_apps/llfbconnecttest/RelWithDebInfo/llfbconnecttest.app
-
- Otherwise the program won't find SLPlugin and will timeout and
- fail after 30 seconds and give you little information as to why.
-
- Running 'dtruss' on plugin test applications will give you a great
- deal of insight into why they aren't activating.
-
diff --git a/indra/test_apps/llfbconnecttest/bookmarks.txt b/indra/test_apps/llfbconnecttest/bookmarks.txt
deleted file mode 100644
index 3995627ea9..0000000000
--- a/indra/test_apps/llfbconnecttest/bookmarks.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-# format is description, url (don't put ',' chars in description :)
-# if no ',' found, whole line is used for both description and url
-Google Home Page,http://www.google.com
-Facebook Home Page,http://www.facebook.com
diff --git a/indra/test_apps/llfbconnecttest/llfbconnecttest.cpp b/indra/test_apps/llfbconnecttest/llfbconnecttest.cpp
deleted file mode 100644
index 483a15c468..0000000000
--- a/indra/test_apps/llfbconnecttest/llfbconnecttest.cpp
+++ /dev/null
@@ -1,2394 +0,0 @@
-/**
- * @file LLFBConnectTest.cpp
- * @brief Facebook Connect Test App
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "indra_constants.h"
-
-#include "llapr.h"
-#include "llerrorcontrol.h"
-
-#include <math.h>
-#include <iomanip>
-#include <sstream>
-#include <ctime>
-
-#include "llfbconnecttest.h"
-
-#if __APPLE__
- #include <GLUT/glut.h>
- #include <CoreFoundation/CoreFoundation.h>
-#else
- #define FREEGLUT_STATIC
- #include "GL/freeglut.h"
- #define GLUI_FREEGLUT
-#endif
-
-#if LL_WINDOWS
-#pragma warning(disable: 4263)
-#pragma warning(disable: 4264)
-#endif
-#include "glui.h"
-
-
-LLFBConnectTest* gApplication = 0;
-static void gluiCallbackWrapper( int control_id );
-
-////////////////////////////////////////////////////////////////////////////////
-//
-static bool isTexture( GLuint texture )
-{
- bool result = false;
-
- // glIsTexture will sometimes return false for real textures... do this instead.
- if(texture != 0)
- result = true;
-
- return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-mediaPanel::mediaPanel()
-{
- mMediaTextureHandle = 0;
- mPickTextureHandle = 0;
- mMediaSource = NULL;
- mPickTexturePixels = NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-mediaPanel::~mediaPanel()
-{
- // delete OpenGL texture handles
- if ( isTexture( mPickTextureHandle ) )
- {
- std::cerr << "remMediaPanel: deleting pick texture " << mPickTextureHandle << std::endl;
- glDeleteTextures( 1, &mPickTextureHandle );
- mPickTextureHandle = 0;
- }
-
- if ( isTexture( mMediaTextureHandle ) )
- {
- std::cerr << "remMediaPanel: deleting media texture " << mMediaTextureHandle << std::endl;
- glDeleteTextures( 1, &mMediaTextureHandle );
- mMediaTextureHandle = 0;
- }
-
- if(mPickTexturePixels)
- {
- delete mPickTexturePixels;
- }
-
- if(mMediaSource)
- {
- delete mMediaSource;
- }
-
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-LLFBConnectTest::LLFBConnectTest( int app_window, int window_width, int window_height ) :
- mVersionMajor( 2 ),
- mVersionMinor( 0 ),
- mVersionPatch( 0 ),
- mMaxPanels( 25 ),
- mViewportAspect( 0 ),
- mAppWindow( app_window ),
- mCurMouseX( 0 ),
- mCurMouseY( 0 ),
- mFuzzyMedia( true ),
- mSelectedPanel( 0 ),
- mDistanceCameraToSelectedGeometry( 0.0f ),
- //mMediaBrowserControlEnableCookies( 0 ),
- mMediaBrowserControlBackButton( 0 ),
- mMediaBrowserControlForwardButton( 0 ),
- //mMediaTimeControlVolume( 100 ),
- //mMediaTimeControlSeekSeconds( 0 ),
- //mGluiMediaTimeControlWindowFlag( true ),
- mGluiMediaBrowserControlWindowFlag( true ),
- mMediaBrowserControlBackButtonFlag( true ),
- mMediaBrowserControlForwardButtonFlag( true ),
- mHomeWebUrl( "https://cryptic-ridge-1632.herokuapp.com/" )
-{
- // debugging spam
- std::cout << std::endl << " GLUT version: " << "3.7.6" << std::endl; // no way to get real version from GLUT
- std::cout << std::endl << " GLUI version: " << GLUI_Master.get_version() << std::endl;
- std::cout << std::endl << "Media Plugin Test version: " << mVersionMajor << "." << mVersionMinor << "." << mVersionPatch << std::endl;
-
- // bookmark title
- mBookmarks.push_back( std::pair< std::string, std::string >( "--- Bookmarks ---", "" ) );
-
- // insert hardcoded URLs here as required for testing
- //mBookmarks.push_back( std::pair< std::string, std::string >( "description", "url" ) );
-
- // read bookmarks from file.
- // note: uses command in ./CmakeLists.txt which copies bookmmarks file from source directory
- // to app directory (WITHOUT build configuration dir) (this is cwd in Windows within MSVC)
- // For example, test_apps\llplugintest and not test_apps\llplugintest\Release
- // This may need to be changed for Mac/Linux builds.
- // See https://jira.lindenlab.com/browse/DEV-31350 for large list of media URLs from AGNI
- const std::string bookmarks_filename( "bookmarks.txt" );
- std::ifstream file_handle( bookmarks_filename.c_str() );
- if ( file_handle.is_open() )
- {
- std::cout << "Reading bookmarks for test" << std::endl;
- while( ! file_handle.eof() )
- {
- std::string line;
- std::getline( file_handle, line );
- if ( file_handle.eof() )
- break;
-
- if ( line.substr( 0, 1 ) != "#" )
- {
- size_t comma_pos = line.find_first_of( ',' );
- if ( comma_pos != std::string::npos )
- {
- std::string description = line.substr( 0, comma_pos );
- std::string url = line.substr( comma_pos + 1 );
- mBookmarks.push_back( std::pair< std::string, std::string >( description, url ) );
- }
- else
- {
- mBookmarks.push_back( std::pair< std::string, std::string >( line, line ) );
- };
- };
- };
- std::cout << "Read " << mBookmarks.size() << " bookmarks" << std::endl;
- }
- else
- {
- std::cout << "Unable to read bookmarks from file: " << bookmarks_filename << std::endl;
- };
-
- // initialize linden lab APR module
- ll_init_apr();
-
- // Set up llerror logging
- {
- LLError::initForApplication(".");
- LLError::setDefaultLevel(LLError::LEVEL_INFO);
- //LLError::setTagLevel("Plugin", LLError::LEVEL_DEBUG);
- }
-
- // lots of randomness in this app
- srand( ( unsigned int )time( 0 ) );
-
- // build GUI
- makeChrome();
-
- // OpenGL initialilzation
- glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
- glClearDepth( 1.0f );
- glEnable( GL_DEPTH_TEST );
- glEnable( GL_COLOR_MATERIAL );
- glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
- glDepthFunc( GL_LEQUAL );
- glEnable( GL_TEXTURE_2D );
- glDisable( GL_BLEND );
- glColor3f( 1.0f, 1.0f, 1.0f );
- glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
- glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
-
- // start with a sane view
- resetView();
-
- // initial media panel
- const int num_initial_panels = 1;
- for( int i = 0; i < num_initial_panels; ++i )
- {
- //addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second );
- addMediaPanel( mHomeWebUrl );
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-LLFBConnectTest::~LLFBConnectTest()
-{
- // delete all media panels
- for( int i = 0; i < (int)mMediaPanels.size(); ++i )
- {
- remMediaPanel( mMediaPanels[ i ] );
- };
-
- // Stop the plugin read thread if it's running.
- LLPluginProcessParent::setUseReadThread(false);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::reshape( int width, int height )
-{
- // update viewport (the active window inside the chrome)
- int viewport_x, viewport_y;
- int viewport_height, viewport_width;
- GLUI_Master.get_viewport_area( &viewport_x, &viewport_y, &viewport_width, &viewport_height );
- mViewportAspect = (float)( viewport_width ) / (float)( viewport_height );
- glViewport( viewport_x, viewport_y, viewport_width, viewport_height );
-
- // save these as we'll need them later
- mWindowWidth = width;
- mWindowHeight = height;
-
- // adjust size of URL bar so it doesn't get clipped
- mUrlEdit->set_w( mWindowWidth - 360 );
-
- // GLUI requires this
- if ( glutGetWindow() != mAppWindow )
- glutSetWindow( mAppWindow );
-
- // trigger re-display
- glutPostRedisplay();
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::bindTexture(GLuint texture, GLint row_length, GLint alignment)
-{
- glEnable( GL_TEXTURE_2D );
-
- glBindTexture( GL_TEXTURE_2D, texture );
- glPixelStorei( GL_UNPACK_ROW_LENGTH, row_length );
- glPixelStorei( GL_UNPACK_ALIGNMENT, alignment );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-bool LLFBConnectTest::checkGLError(const char *name)
-{
- bool result = false;
- GLenum error = glGetError();
-
- if(error != GL_NO_ERROR)
- {
- // For some reason, glGenTextures is returning GL_INVALID_VALUE...
- std::cout << name << " ERROR 0x" << std::hex << error << std::dec << std::endl;
- result = true;
- }
-
- return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-GLfloat LLFBConnectTest::distanceToCamera( GLfloat point_x, GLfloat point_y, GLfloat point_z )
-{
- GLdouble camera_pos_x = 0.0f;
- GLdouble camera_pos_y = 0.0f;
- GLdouble camera_pos_z = 0.0f;
-
- GLdouble modelMatrix[16];
- GLdouble projMatrix[16];
- GLint viewport[4];
-
- glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
- glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
- glGetIntegerv(GL_VIEWPORT, viewport);
-
- gluUnProject(
- (viewport[2]-viewport[0])/2 , (viewport[3]-viewport[1])/2,
- 0.0,
- modelMatrix, projMatrix, viewport,
- &camera_pos_x, &camera_pos_y, &camera_pos_z );
-
- GLfloat distance =
- sqrt( ( camera_pos_x - point_x ) * ( camera_pos_x - point_x ) +
- ( camera_pos_y - point_y ) * ( camera_pos_y - point_y ) +
- ( camera_pos_z - point_z ) * ( camera_pos_z - point_z ) );
-
- return distance;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::drawGeometry( int panel, bool selected )
-{
- // texture coordinates for each panel
- GLfloat non_opengl_texture_coords[ 8 ] = { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f };
- GLfloat opengl_texture_coords[ 8 ] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f };
-
- GLfloat *texture_coords = mMediaPanels[ panel ]->mAppTextureCoordsOpenGL?opengl_texture_coords:non_opengl_texture_coords;
-
- // base coordinates for each panel
- GLfloat base_vertex_pos[ 8 ] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f };
-
- // calculate posiitons
- const int num_panels = (int)mMediaPanels.size();
- const int num_rows = (int)sqrt( (float)num_panels );
- const int num_cols = num_panels / num_rows;
- const int panel_x = ( panel / num_rows );
- const int panel_y = ( panel % num_rows );
-
- // default spacing is small - make it larger if checkbox set - for testing positional audio
- float spacing = 0.1f;
- //if ( mLargePanelSpacing )
- // spacing = 2.0f;
-
- const GLfloat offset_x = num_cols * ( 1.0 + spacing ) / 2;
- const GLfloat offset_y = num_rows * ( 1.0 + spacing ) / 2;
-
- // Adjust for media aspect ratios
- {
- float aspect = 1.0f;
-
- if(mMediaPanels[ panel ]->mMediaHeight != 0)
- {
- aspect = (float)mMediaPanels[ panel ]->mMediaWidth / (float)mMediaPanels[ panel ]->mMediaHeight;
- }
-
- if(aspect > 1.0f)
- {
- // media is wider than it is high -- adjust the top and bottom in
- for( int corner = 0; corner < 4; ++corner )
- {
- float temp = base_vertex_pos[corner * 2 + 1];
-
- if(temp < 0.5f)
- temp += 0.5 - (0.5f / aspect);
- else
- temp -= 0.5 - (0.5f / aspect);
-
- base_vertex_pos[corner * 2 + 1] = temp;
- }
- }
- else if(aspect < 1.0f)
- {
- // media is higher than it is wide -- adjust the left and right sides in
- for( int corner = 0; corner < 4; ++corner )
- {
- float temp = base_vertex_pos[corner * 2];
-
- if(temp < 0.5f)
- temp += 0.5f - (0.5f * aspect);
- else
- temp -= 0.5f - (0.5f * aspect);
-
- base_vertex_pos[corner * 2] = temp;
- }
- }
- }
-
- glBegin( GL_QUADS );
- for( int corner = 0; corner < 4; ++corner )
- {
- glTexCoord2f( texture_coords[ corner * 2 ], texture_coords[ corner * 2 + 1 ] );
- GLfloat x = base_vertex_pos[ corner * 2 ] + panel_x * ( 1.0 + spacing ) - offset_x + spacing / 2.0f;
- GLfloat y = base_vertex_pos[ corner * 2 + 1 ] + panel_y * ( 1.0 + spacing ) - offset_y + spacing / 2.0f;
-
- glVertex3f( x, y, 0.0f );
- };
- glEnd();
-
- // calculate distance to this panel if it's selected
- if ( selected )
- {
- GLfloat point_x = base_vertex_pos[ 0 ] + panel_x * ( 1.0 + spacing ) - offset_x + spacing / 2.0f;
- GLfloat point_y = base_vertex_pos[ 0 + 1 ] + panel_y * ( 1.0 + spacing ) - offset_y + spacing / 2.0f;
- GLfloat point_z = 0.0f;
- mDistanceCameraToSelectedGeometry = distanceToCamera( point_x, point_y, point_z );
- };
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::startPanelHighlight( float red, float green, float blue, float line_width )
-{
- glPushAttrib( GL_ALL_ATTRIB_BITS );
- glEnable( GL_POLYGON_OFFSET_FILL );
- glPolygonOffset( -2.5f, -2.5f );
- glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
- glLineWidth( line_width );
- glColor3f( red, green, blue );
- glDisable( GL_TEXTURE_2D );
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::endPanelHighlight()
-{
- glPopAttrib();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::draw( int draw_type )
-{
- for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
- {
- // drawing pick texture
- if ( draw_type == DrawTypePickTexture )
- {
- // only bother with pick if we have something to render
- // Actually, we need to pick even if we're not ready to render.
- // Otherwise you can't select and remove a panel which has gone bad.
- //if ( mMediaPanels[ panel ]->mReadyToRender )
- {
- glMatrixMode( GL_TEXTURE );
- glPushMatrix();
-
- // pick texture is a power of 2 so no need to scale
- glLoadIdentity();
-
- // bind to media texture
- glLoadIdentity();
- bindTexture( mMediaPanels[ panel ]->mPickTextureHandle );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
-
- // draw geometry using pick texture
- drawGeometry( panel, false );
-
- glMatrixMode( GL_TEXTURE );
- glPopMatrix();
- };
- }
- else
- if ( draw_type == DrawTypeMediaTexture )
- {
- bool texture_valid = false;
- bool plugin_exited = false;
-
- if(mMediaPanels[ panel ]->mMediaSource)
- {
- texture_valid = mMediaPanels[ panel ]->mMediaSource->textureValid();
- plugin_exited = mMediaPanels[ panel ]->mMediaSource->isPluginExited();
- }
-
- // save texture matrix (changes for each panel)
- glMatrixMode( GL_TEXTURE );
- glPushMatrix();
-
- // only process texture if the media is ready to draw
- // (we still want to draw the geometry)
- if ( mMediaPanels[ panel ]->mReadyToRender && texture_valid )
- {
- // bind to media texture
- bindTexture( mMediaPanels[ panel ]->mMediaTextureHandle );
-
- if ( mFuzzyMedia )
- {
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- }
- else
- {
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
- }
-
- // scale to fit panel
- glScalef( mMediaPanels[ panel ]->mTextureScaleX,
- mMediaPanels[ panel ]->mTextureScaleY,
- 1.0f );
- };
-
- float intensity = plugin_exited?0.25f:1.0f;
-
- // highlight the selected panel
- if ( mSelectedPanel && ( mMediaPanels[ panel ]->mId == mSelectedPanel->mId ) )
- {
- startPanelHighlight( intensity, intensity, 0.0f, 5.0f );
- drawGeometry( panel, true );
- endPanelHighlight();
- }
- else
- // this panel not able to render yet since it
- // doesn't have enough information
- if ( !mMediaPanels[ panel ]->mReadyToRender )
- {
- startPanelHighlight( intensity, 0.0f, 0.0f, 2.0f );
- drawGeometry( panel, false );
- endPanelHighlight();
- }
- else
- // just display a border around the media
- {
- startPanelHighlight( 0.0f, intensity, 0.0f, 2.0f );
- drawGeometry( panel, false );
- endPanelHighlight();
- };
-
- if ( mMediaPanels[ panel ]->mReadyToRender && texture_valid )
- {
- // draw visual geometry
- drawGeometry( panel, false );
- }
-
- // restore texture matrix (changes for each panel)
- glMatrixMode( GL_TEXTURE );
- glPopMatrix();
- };
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::display()
-{
- // GLUI requires this
- if ( glutGetWindow() != mAppWindow )
- glutSetWindow( mAppWindow );
-
- // start with a clean slate
- glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-
- // set up OpenGL view
- glMatrixMode( GL_PROJECTION );
- glLoadIdentity();
- glFrustum( -mViewportAspect * 0.04f, mViewportAspect * 0.04f, -0.04f, 0.04f, 0.1f, 50.0f );
- glMatrixMode( GL_MODELVIEW );
- glLoadIdentity();
- glTranslatef( 0.0, 0.0, 0.0f );
- glTranslatef( mViewPos[ 0 ], mViewPos[ 1 ], -mViewPos[ 2 ] );
- glMultMatrixf( mViewRotation );
-
- // draw pick texture
- draw( DrawTypePickTexture );
-
- // read colors and get coordinate values
- glReadPixels( mCurMouseX, mCurMouseY, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, mPixelReadColor );
-
- // clear the pick render (otherwise it may depth-fight with the textures rendered later)
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-
- // draw visible geometry
- draw( DrawTypeMediaTexture );
-
- glutSwapBuffers();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::idle()
-{
-// checkGLError("LLFBConnectTest::idle");
-
- // GLUI requires this
- if ( glutGetWindow() != mAppWindow )
- glutSetWindow( mAppWindow );
-
- // random creation/destruction of panels enabled?
-/*
- const time_t panel_timeout_time = 5;
- if ( mRandomPanelCount )
- {
- // time for a change
- static time_t last_panel_time = 0;
- if ( time( NULL ) - last_panel_time > panel_timeout_time )
- {
- if ( rand() % 2 == 0 )
- {
- if ( mMediaPanels.size() < 16 )
- {
- std::cout << "Randomly adding new panel" << std::endl;
- addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second );
- };
- }
- else
- {
- if ( mMediaPanels.size() > 0 )
- {
- std::cout << "Deleting selected panel" << std::endl;
- remMediaPanel( mSelectedPanel );
- };
- };
- time( &last_panel_time );
- };
- };
-
- // random selection of bookmarks enabled?
- const time_t bookmark_timeout_time = 5;
- if ( mRandomBookmarks )
- {
- // time for a change
- static time_t last_bookmark_time = 0;
- if ( time( NULL ) - last_bookmark_time > bookmark_timeout_time )
- {
- // go to a different random bookmark on each panel
- for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
- {
- std::string uri = mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second;
-
- std::cout << "Random: navigating to : " << uri << std::endl;
-
- std::string mime_type = mimeTypeFromUrl( uri );
-
- if ( mime_type != mMediaPanels[ panel ]->mMimeType )
- {
- replaceMediaPanel( mMediaPanels[ panel ], uri );
- }
- else
- {
- mMediaPanels[ panel ]->mMediaSource->loadURI( uri );
- mMediaPanels[ panel ]->mMediaSource->start();
- };
- };
-
- time( &last_bookmark_time );
- };
- };
-*/
- // update UI
- if ( mSelectedPanel )
- {
- // set volume based on slider if we have time media
- //if ( mGluiMediaTimeControlWindowFlag )
- //{
- // mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f );
- //};
-
- // NOTE: it is absurd that we need cache the state of GLUI controls
- // but enabling/disabling controls drags framerate from 500+
- // down to 15. Not a problem for plugin system - only this test
- // enable/disable time based UI controls based on type of plugin
- if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() )
- {
- /*
- if ( ! mGluiMediaTimeControlWindowFlag )
- {
- mGluiMediaTimeControlWindow->enable();
- mGluiMediaTimeControlWindowFlag = true;
- };
- */
- }
- else
- {
- /*
- if ( mGluiMediaTimeControlWindowFlag )
- {
- mGluiMediaTimeControlWindow->disable();
- mGluiMediaTimeControlWindowFlag = false;
- };
- */
- };
-
- // enable/disable browser based UI controls based on type of plugin
- if ( mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() )
- {
- if ( ! mGluiMediaBrowserControlWindowFlag )
- {
- mGluiMediaBrowserControlWindow->enable();
- mGluiMediaBrowserControlWindowFlag = true;
- };
- }
- else
- {
- if ( mGluiMediaBrowserControlWindowFlag )
- {
- mGluiMediaBrowserControlWindow->disable();
- mGluiMediaBrowserControlWindowFlag = false;
- };
- };
-
- // enable/disable browser back button depending on browser history
- if ( mSelectedPanel->mMediaSource->getHistoryBackAvailable() )
- {
- if ( ! mMediaBrowserControlBackButtonFlag )
- {
- mMediaBrowserControlBackButton->enable();
- mMediaBrowserControlBackButtonFlag = true;
- };
- }
- else
- {
- if ( mMediaBrowserControlBackButtonFlag )
- {
- mMediaBrowserControlBackButton->disable();
- mMediaBrowserControlBackButtonFlag = false;
- };
- };
-
- // enable/disable browser forward button depending on browser history
- if ( mSelectedPanel->mMediaSource->getHistoryForwardAvailable() )
- {
- if ( ! mMediaBrowserControlForwardButtonFlag )
- {
- mMediaBrowserControlForwardButton->enable();
- mMediaBrowserControlForwardButtonFlag = true;
- };
- }
- else
- {
- if ( mMediaBrowserControlForwardButtonFlag )
- {
- mMediaBrowserControlForwardButton->disable();
- mMediaBrowserControlForwardButtonFlag = false;
- };
- };
-
- // NOTE: This is *very* slow and not worth optimising
- updateStatusBar();
- };
-
- // update all the panels
- for( int panel_index = 0; panel_index < (int)mMediaPanels.size(); ++panel_index )
- {
- mediaPanel *panel = mMediaPanels[ panel_index ];
-
- // call plugins idle function so it can potentially update itself
- panel->mMediaSource->idle();
-
- // update each media panel
- updateMediaPanel( panel );
-
- LLRect dirty_rect;
- if ( ! panel->mMediaSource->textureValid() )
- {
- //std::cout << "texture invalid, skipping update..." << std::endl;
- }
- else
- if ( panel &&
- ( panel->mMediaWidth != panel->mMediaSource->getWidth() ||
- panel->mMediaHeight != panel->mMediaSource->getHeight() ) )
- {
- //std::cout << "Resize in progress, skipping update..." << std::endl;
- }
- else
- if ( panel->mMediaSource->getDirty( &dirty_rect ) )
- {
- const unsigned char* pixels = panel->mMediaSource->getBitsData();
- if ( pixels && isTexture(panel->mMediaTextureHandle))
- {
- int x_offset = dirty_rect.mLeft;
- int y_offset = dirty_rect.mBottom;
- int width = dirty_rect.mRight - dirty_rect.mLeft;
- int height = dirty_rect.mTop - dirty_rect.mBottom;
-
- if((dirty_rect.mRight <= panel->mTextureWidth) && (dirty_rect.mTop <= panel->mTextureHeight))
- {
- // Offset the pixels pointer properly
- pixels += ( y_offset * panel->mMediaSource->getTextureDepth() * panel->mMediaSource->getBitsWidth() );
- pixels += ( x_offset * panel->mMediaSource->getTextureDepth() );
-
- // set up texture
- bindTexture( panel->mMediaTextureHandle, panel->mMediaSource->getBitsWidth() );
- if ( mFuzzyMedia )
- {
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- }
- else
- {
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
- };
-
- checkGLError("glTexParameteri");
-
- if(panel->mMediaSource->getTextureFormatSwapBytes())
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
- checkGLError("glPixelStorei");
- }
-
- // draw portion that changes into texture
- glTexSubImage2D( GL_TEXTURE_2D, 0,
- x_offset,
- y_offset,
- width,
- height,
- panel->mMediaSource->getTextureFormatPrimary(),
- panel->mMediaSource->getTextureFormatType(),
- pixels );
-
- if(checkGLError("glTexSubImage2D"))
- {
- std::cerr << " panel ID=" << panel->mId << std::endl;
- std::cerr << " texture size = " << panel->mTextureWidth << " x " << panel->mTextureHeight << std::endl;
- std::cerr << " media size = " << panel->mMediaWidth << " x " << panel->mMediaHeight << std::endl;
- std::cerr << " dirty rect = " << dirty_rect.mLeft << ", " << dirty_rect.mBottom << ", " << dirty_rect.mRight << ", " << dirty_rect.mTop << std::endl;
- std::cerr << " texture width = " << panel->mMediaSource->getBitsWidth() << std::endl;
- std::cerr << " format primary = 0x" << std::hex << panel->mMediaSource->getTextureFormatPrimary() << std::dec << std::endl;
- std::cerr << " format type = 0x" << std::hex << panel->mMediaSource->getTextureFormatType() << std::dec << std::endl;
- std::cerr << " pixels = " << (void*)pixels << std::endl;
- }
-
- if(panel->mMediaSource->getTextureFormatSwapBytes())
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
- checkGLError("glPixelStorei");
- }
-
- panel->mMediaSource->resetDirty();
-
- panel->mReadyToRender = true;
- }
- else
- {
- std::cerr << "dirty rect is outside current media size, skipping update" << std::endl;
- }
- };
- };
- };
-
- // GLUI requires this
- if ( glutGetWindow() != mAppWindow )
- glutSetWindow( mAppWindow );
-
- // trigger re-display
- glutPostRedisplay();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::windowPosToTexturePos( int window_x, int window_y,
- int& media_x, int& media_y,
- int& id )
-{
- if ( ! mSelectedPanel )
- {
- media_x = 0;
- media_y = 0;
- id = 0;
- return;
- };
-
- // record cursor poisiton for a readback next frame
- mCurMouseX = window_x;
- // OpenGL app == coordinate system this way
- // NOTE: unrelated to settings in plugin - this
- // is just for this app
- mCurMouseY = mWindowHeight - window_y;
-
- // extract x (0..1023, y (0..1023) and id (0..15) from RGB components
- unsigned long pixel_read_color_bits = ( mPixelReadColor[ 0 ] << 16 ) | ( mPixelReadColor[ 1 ] << 8 ) | mPixelReadColor[ 2 ];
- int texture_x = pixel_read_color_bits & 0x3ff;
- int texture_y = ( pixel_read_color_bits >> 10 ) & 0x3ff;
- id = ( pixel_read_color_bits >> 20 ) & 0x0f;
-
- // scale to size of media (1024 because we use 10 bits for X and Y from 24)
- media_x = (int)( ( (float)mSelectedPanel->mMediaWidth * (float)texture_x ) / 1024.0f );
- media_y = (int)( ( (float)mSelectedPanel->mMediaHeight * (float)texture_y ) / 1024.0f );
-
- // we assume the plugin uses an inverted coordinate scheme like OpenGL
- // if not, the plugin code inverts the Y coordinate for us - we don't need to
- media_y = mSelectedPanel->mMediaHeight - media_y;
-
- if ( media_x > 0 && media_y > 0 )
- {
- //std::cout << " mouse coords: " << mCurMouseX << " x " << mCurMouseY << " and id = " << id << std::endl;
- //std::cout << "raw texture coords: " << texture_x << " x " << texture_y << " and id = " << id << std::endl;
- //std::cout << " media coords: " << media_x << " x " << media_y << " and id = " << id << std::endl;
- //std::cout << std::endl;
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::selectPanelById( int id )
-{
- for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
- {
- if ( mMediaPanels[ panel ]->mId == id )
- {
- selectPanel(mMediaPanels[ panel ]);
- return;
- };
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::selectPanel( mediaPanel* panel )
-{
- if( mSelectedPanel == panel )
- return;
-
- // turn off volume before we delete it
- if( mSelectedPanel && mSelectedPanel->mMediaSource )
- {
- mSelectedPanel->mMediaSource->setVolume( 0.0f );
- mSelectedPanel->mMediaSource->setPriority( LLPluginClassMedia::PRIORITY_LOW );
- };
-
- mSelectedPanel = panel;
-
- if( mSelectedPanel && mSelectedPanel->mMediaSource )
- {
- //mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f );
- mSelectedPanel->mMediaSource->setPriority( LLPluginClassMedia::PRIORITY_NORMAL );
-
- if(!mSelectedPanel->mStartUrl.empty())
- {
- mUrlEdit->set_text(const_cast<char*>(mSelectedPanel->mStartUrl.c_str()) );
- }
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-mediaPanel* LLFBConnectTest::findMediaPanel( LLPluginClassMedia* source )
-{
- mediaPanel *result = NULL;
-
- for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
- {
- if ( mMediaPanels[ panel ]->mMediaSource == source )
- {
- result = mMediaPanels[ panel ];
- }
- }
-
- return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-mediaPanel* LLFBConnectTest::findMediaPanel( const std::string &target_name )
-{
- mediaPanel *result = NULL;
-
- for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
- {
- if ( mMediaPanels[ panel ]->mTarget == target_name )
- {
- result = mMediaPanels[ panel ];
- }
- }
-
- return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::navigateToNewURI( std::string uri )
-{
- if ( uri.length() )
- {
- std::string mime_type = mimeTypeFromUrl( uri );
-
- if ( !mSelectedPanel->mMediaSource->isPluginExited() && (mime_type == mSelectedPanel->mMimeType) )
- {
- std::cout << "MIME type is the same" << std::endl;
- mSelectedPanel->mMediaSource->loadURI( uri );
- mSelectedPanel->mMediaSource->start();
- mBookmarkList->do_selection( 0 );
- }
- else
- {
- std::cout << "MIME type changed or plugin had exited" << std::endl;
- replaceMediaPanel( mSelectedPanel, uri );
- mBookmarkList->do_selection( 0 );
- }
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::initUrlHistory( std::string uris )
-{
- if ( uris.length() > 0 )
- {
- std::cout << "init URL : " << uris << std::endl;
- LLSD historySD;
-
- char *cstr, *p;
- cstr = new char[uris.size()+1];
- strcpy(cstr, uris.c_str());
- const char *DELIMS = " ,;";
- p = strtok(cstr, DELIMS);
- while (p != NULL) {
- historySD.insert(0, p);
- p = strtok(NULL, DELIMS);
- }
- mSelectedPanel->mMediaSource->initializeUrlHistory(historySD);
- delete[] cstr;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::gluiCallback( int control_id )
-{
- if ( control_id == mIdBookmarks )
- {
- std::string uri = mBookmarks[ mSelBookmark ].second;
-
- navigateToNewURI( uri );
- }
- else
- if ( control_id == mIdUrlEdit)
- {
- std::string uri = mUrlEdit->get_text();
-
- navigateToNewURI( uri );
- }
-/*
- else
- if ( control_id == mIdUrlInitHistoryEdit )
- {
- std::string uri = mUrlInitHistoryEdit->get_text();
-
- initUrlHistory( uri );
- }
- else
- if ( control_id == mIdControlAddPanel )
- {
- addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second );
- }
- else
- if ( control_id == mIdControlRemPanel )
- {
- remMediaPanel( mSelectedPanel );
- }
- else
- if ( control_id == mIdDisableTimeout )
- {
- // Set the "disable timeout" flag for all active plugins.
- for( int i = 0; i < (int)mMediaPanels.size(); ++i )
- {
- mMediaPanels[ i ]->mMediaSource->setDisableTimeout(mDisableTimeout);
- }
- }
- else
- if ( control_id == mIdUsePluginReadThread )
- {
- LLPluginProcessParent::setUseReadThread(mUsePluginReadThread);
- }
- else
- if ( control_id == mIdControlCrashPlugin )
- {
- // send message to plugin and ask it to crash
- // (switch out for ReleaseCandidate version :) )
- if(mSelectedPanel && mSelectedPanel->mMediaSource)
- {
- mSelectedPanel->mMediaSource->crashPlugin();
- }
- }
- else
- if ( control_id == mIdControlHangPlugin )
- {
- // send message to plugin and ask it to hang
- // (switch out for ReleaseCandidate version :) )
- if(mSelectedPanel && mSelectedPanel->mMediaSource)
- {
- mSelectedPanel->mMediaSource->hangPlugin();
- }
- }
- else
-*/
- if ( control_id == mIdControlExitApp )
- {
- // text for exiting plugin system cleanly
- delete this; // clean up
- exit( 0 );
- }
-/*
- else
- if ( control_id == mIdMediaTimeControlPlay )
- {
- if ( mSelectedPanel )
- {
- mSelectedPanel->mMediaSource->setLoop( false );
- mSelectedPanel->mMediaSource->start();
- };
- }
- else
- if ( control_id == mIdMediaTimeControlLoop )
- {
- if ( mSelectedPanel )
- {
- mSelectedPanel->mMediaSource->setLoop( true );
- mSelectedPanel->mMediaSource->start();
- };
- }
- else
- if ( control_id == mIdMediaTimeControlPause )
- {
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->pause();
- }
- else
- if ( control_id == mIdMediaTimeControlStop )
- {
- if ( mSelectedPanel )
- {
- mSelectedPanel->mMediaSource->stop();
- };
- }
- else
- if ( control_id == mIdMediaTimeControlSeek )
- {
- if ( mSelectedPanel )
- {
- // get value from spinner
- float seconds_to_seek = mMediaTimeControlSeekSeconds;
- mSelectedPanel->mMediaSource->seek( seconds_to_seek );
- mSelectedPanel->mMediaSource->start();
- };
- }
- else
- if ( control_id == mIdMediaTimeControlRewind )
- {
- if ( mSelectedPanel )
- {
- mSelectedPanel->mMediaSource->setLoop( false );
- mSelectedPanel->mMediaSource->start(-2.0f);
- };
- }
- else
- if ( control_id == mIdMediaTimeControlFastForward )
- {
- if ( mSelectedPanel )
- {
- mSelectedPanel->mMediaSource->setLoop( false );
- mSelectedPanel->mMediaSource->start(2.0f);
- };
- }
- else
-*/
- if ( control_id == mIdMediaBrowserControlBack )
- {
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->browse_back();
- }
- else
- if ( control_id == mIdMediaBrowserControlStop )
- {
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->browse_stop();
- }
- else
- if ( control_id == mIdMediaBrowserControlForward )
- {
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->browse_forward();
- }
- else
- if ( control_id == mIdMediaBrowserControlHome )
- {
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->loadURI( mHomeWebUrl );
- }
- else
- if ( control_id == mIdMediaBrowserControlReload )
- {
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->browse_reload( true );
- }
-/*
- else
- if ( control_id == mIdMediaBrowserControlClearCache )
- {
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->clear_cache();
- }
- else
- if ( control_id == mIdMediaBrowserControlClearCookies )
- {
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->clear_cookies();
- }
- else
- if ( control_id == mIdMediaBrowserControlEnableCookies )
- {
- if ( mSelectedPanel )
- {
- if ( mMediaBrowserControlEnableCookies )
- {
- mSelectedPanel->mMediaSource->enable_cookies( true );
- }
- else
- {
- mSelectedPanel->mMediaSource->enable_cookies( false );
- }
- };
- };
-*/
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::keyboard( int key )
-{
- //if ( key == 'a' || key == 'A' )
- // addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second );
- //else
- //if ( key == 'r' || key == 'R' )
- // remMediaPanel( mSelectedPanel );
- //else
- //if ( key == 'd' || key == 'D' )
- // dumpPanelInfo();
- //else
- if ( key == 27 )
- {
- std::cout << "Application finished - exiting..." << std::endl;
- delete this;
- exit( 0 );
- };
-
- mSelectedPanel->mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_DOWN, key, 0 , LLSD());
- mSelectedPanel->mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_UP, key, 0, LLSD());
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::mouseButton( int button, int state, int x, int y )
-{
- if ( button == GLUT_LEFT_BUTTON )
- {
- if ( state == GLUT_DOWN )
- {
- int media_x, media_y, id;
- windowPosToTexturePos( x, y, media_x, media_y, id );
-
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_DOWN, 0, media_x, media_y, 0 );
- }
- else
- if ( state == GLUT_UP )
- {
- int media_x, media_y, id;
- windowPosToTexturePos( x, y, media_x, media_y, id );
-
- // only select a panel if we're on a panel
- // (HACK: strictly speaking this rules out clicking on
- // the origin of a panel but that's very unlikely)
- if ( media_x > 0 && media_y > 0 )
- {
- selectPanelById( id );
-
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_UP, 0, media_x, media_y, 0 );
- };
- };
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::mousePassive( int x, int y )
-{
- int media_x, media_y, id;
- windowPosToTexturePos( x, y, media_x, media_y, id );
-
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, media_x, media_y, 0 );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::mouseMove( int x, int y )
-{
- int media_x, media_y, id;
- windowPosToTexturePos( x, y, media_x, media_y, id );
-
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, media_x, media_y, 0 );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::makeChrome()
-{
- // IDs used by GLUI
- int start_id = 0x1000;
-
- // right side window - geometry manipulators
-#if __APPLE__
- // the Apple GLUT implementation doesn't seem to set the graphic offset of subwindows correctly when they overlap in certain ways.
- // Use a separate controls window in this case.
- // GLUI window at right containing manipulation controls and other buttons
- int x = glutGet(GLUT_WINDOW_X) + glutGet(GLUT_WINDOW_WIDTH) + 4;
- int y = glutGet(GLUT_WINDOW_Y);
- GLUI* right_glui_window = GLUI_Master.create_glui( "", 0, x, y );
-#else
- GLUI* right_glui_window = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_RIGHT );
-#endif
- mViewRotationCtrl = right_glui_window->add_rotation( "Rotation", mViewRotation );
- mViewTranslationCtrl = right_glui_window->add_translation( "Translate", GLUI_TRANSLATION_XY, mViewPos );
- mViewTranslationCtrl->set_speed( 0.01f );
- mViewScaleCtrl = right_glui_window->add_translation( "Scale", GLUI_TRANSLATION_Z, &mViewPos[ 2 ] );
- mViewScaleCtrl->set_speed( 0.05f );
- right_glui_window->set_main_gfx_window( mAppWindow );
-
- // right side window - app controls
- /*
- mIdControlAddPanel = start_id++;
- right_glui_window->add_statictext( "" );
- right_glui_window->add_separator();
- right_glui_window->add_statictext( "" );
- right_glui_window->add_button( "Add panel", mIdControlAddPanel, gluiCallbackWrapper );
- right_glui_window->add_statictext( "" );
- mIdControlRemPanel = start_id++;
- right_glui_window->add_button( "Rem panel", mIdControlRemPanel, gluiCallbackWrapper );
- right_glui_window->add_statictext( "" );
- right_glui_window->add_separator();
- right_glui_window->add_statictext( "" );
- mIdControlCrashPlugin = start_id++;
- right_glui_window->add_button( "Crash plugin", mIdControlCrashPlugin, gluiCallbackWrapper );
- mIdControlHangPlugin = start_id++;
- right_glui_window->add_button( "Hang plugin", mIdControlHangPlugin, gluiCallbackWrapper );
- */
- right_glui_window->add_statictext( "" );
- right_glui_window->add_separator();
- right_glui_window->add_statictext( "" );
- mIdControlExitApp = start_id++;
- right_glui_window->add_button( "Exit app", mIdControlExitApp, gluiCallbackWrapper );
-
- //// top window - holds bookmark UI
- mIdBookmarks = start_id++;
- mSelBookmark = 0;
- GLUI* glui_window_top = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
- mBookmarkList = glui_window_top->add_listbox( "", &mSelBookmark, mIdBookmarks, gluiCallbackWrapper );
- // only add the first 50 bookmarks - list can be very long sometimes (30,000+)
- // when testing list of media URLs from AGNI for example
- for( unsigned int each = 0; each < mBookmarks.size() && each < 50; ++each )
- mBookmarkList->add_item( each, const_cast< char* >( mBookmarks[ each ].first.c_str() ) );
- glui_window_top->set_main_gfx_window( mAppWindow );
-
- glui_window_top->add_column( false );
- mIdUrlEdit = start_id++;
- mUrlEdit = glui_window_top->add_edittext( "Url:", GLUI_EDITTEXT_TEXT, 0, mIdUrlEdit, gluiCallbackWrapper );
- mUrlEdit->set_w( 600 );
- //GLUI* glui_window_top2 = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
- //mIdUrlInitHistoryEdit = start_id++;
- //mUrlInitHistoryEdit = glui_window_top2->add_edittext( "Init History (separate by commas or semicolons):",
- // GLUI_EDITTEXT_TEXT, 0, mIdUrlInitHistoryEdit, gluiCallbackWrapper );
- //mUrlInitHistoryEdit->set_w( 800 );
-
- // top window - media controls for "time" media types (e.g. movies)
-/*
- mGluiMediaTimeControlWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
- mGluiMediaTimeControlWindow->set_main_gfx_window( mAppWindow );
- mIdMediaTimeControlPlay = start_id++;
- mGluiMediaTimeControlWindow->add_button( "PLAY", mIdMediaTimeControlPlay, gluiCallbackWrapper );
- mGluiMediaTimeControlWindow->add_column( false );
- mIdMediaTimeControlLoop = start_id++;
- mGluiMediaTimeControlWindow->add_button( "LOOP", mIdMediaTimeControlLoop, gluiCallbackWrapper );
- mGluiMediaTimeControlWindow->add_column( false );
- mIdMediaTimeControlPause = start_id++;
- mGluiMediaTimeControlWindow->add_button( "PAUSE", mIdMediaTimeControlPause, gluiCallbackWrapper );
- mGluiMediaTimeControlWindow->add_column( false );
-
- GLUI_Button *button;
- mIdMediaTimeControlRewind = start_id++;
- button = mGluiMediaTimeControlWindow->add_button( "<<", mIdMediaTimeControlRewind, gluiCallbackWrapper );
- button->set_w(30);
- mGluiMediaTimeControlWindow->add_column( false );
- mIdMediaTimeControlFastForward = start_id++;
- button = mGluiMediaTimeControlWindow->add_button( ">>", mIdMediaTimeControlFastForward, gluiCallbackWrapper );
- button->set_w(30);
-
- mGluiMediaTimeControlWindow->add_column( true );
-
- mIdMediaTimeControlStop = start_id++;
- mGluiMediaTimeControlWindow->add_button( "STOP", mIdMediaTimeControlStop, gluiCallbackWrapper );
- mGluiMediaTimeControlWindow->add_column( false );
- mIdMediaTimeControlVolume = start_id++;
- GLUI_Spinner* spinner = mGluiMediaTimeControlWindow->add_spinner( "Volume", 2, &mMediaTimeControlVolume, mIdMediaTimeControlVolume, gluiCallbackWrapper);
- spinner->set_float_limits( 0, 100 );
- mGluiMediaTimeControlWindow->add_column( true );
- mIdMediaTimeControlSeekSeconds = start_id++;
- spinner = mGluiMediaTimeControlWindow->add_spinner( "", 2, &mMediaTimeControlSeekSeconds, mIdMediaTimeControlSeekSeconds, gluiCallbackWrapper);
- spinner->set_float_limits( 0, 200 );
- spinner->set_w( 32 );
- spinner->set_speed( 0.025f );
- mGluiMediaTimeControlWindow->add_column( false );
- mIdMediaTimeControlSeek = start_id++;
- mGluiMediaTimeControlWindow->add_button( "SEEK", mIdMediaTimeControlSeek, gluiCallbackWrapper );
- mGluiMediaTimeControlWindow->add_column( false );
-*/
-
- // top window - media controls for "browser" media types (e.g. web browser)
- mGluiMediaBrowserControlWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
- mGluiMediaBrowserControlWindow->set_main_gfx_window( mAppWindow );
- mIdMediaBrowserControlBack = start_id++;
- mMediaBrowserControlBackButton = mGluiMediaBrowserControlWindow->add_button( "BACK", mIdMediaBrowserControlBack, gluiCallbackWrapper );
- mGluiMediaBrowserControlWindow->add_column( false );
- mIdMediaBrowserControlStop = start_id++;
- mGluiMediaBrowserControlWindow->add_button( "STOP", mIdMediaBrowserControlStop, gluiCallbackWrapper );
- mGluiMediaBrowserControlWindow->add_column( false );
- mIdMediaBrowserControlForward = start_id++;
- mMediaBrowserControlForwardButton = mGluiMediaBrowserControlWindow->add_button( "FORWARD", mIdMediaBrowserControlForward, gluiCallbackWrapper );
- mGluiMediaBrowserControlWindow->add_column( false );
- mIdMediaBrowserControlHome = start_id++;
- mGluiMediaBrowserControlWindow->add_button( "HOME", mIdMediaBrowserControlHome, gluiCallbackWrapper );
- mGluiMediaBrowserControlWindow->add_column( false );
- mIdMediaBrowserControlReload = start_id++;
- mGluiMediaBrowserControlWindow->add_button( "RELOAD", mIdMediaBrowserControlReload, gluiCallbackWrapper );
- mGluiMediaBrowserControlWindow->add_column( false );
- /*
- mIdMediaBrowserControlClearCache = start_id++;
- mGluiMediaBrowserControlWindow->add_button( "CLEAR CACHE", mIdMediaBrowserControlClearCache, gluiCallbackWrapper );
- mGluiMediaBrowserControlWindow->add_column( false );
- mIdMediaBrowserControlClearCookies = start_id++;
- mGluiMediaBrowserControlWindow->add_button( "CLEAR COOKIES", mIdMediaBrowserControlClearCookies, gluiCallbackWrapper );
- mGluiMediaBrowserControlWindow->add_column( false );
- mIdMediaBrowserControlEnableCookies = start_id++;
- mMediaBrowserControlEnableCookies = 0;
- mGluiMediaBrowserControlWindow->add_checkbox( "Enable Cookies", &mMediaBrowserControlEnableCookies, mIdMediaBrowserControlEnableCookies, gluiCallbackWrapper );
-
- // top window - misc controls
- GLUI* glui_window_misc_control = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
- mIdRandomPanelCount = start_id++;
- mRandomPanelCount = 0;
- glui_window_misc_control->add_checkbox( "Randomize panel count", &mRandomPanelCount, mIdRandomPanelCount, gluiCallbackWrapper );
- glui_window_misc_control->set_main_gfx_window( mAppWindow );
- glui_window_misc_control->add_column( true );
- mIdRandomBookmarks = start_id++;
- mRandomBookmarks = 0;
- glui_window_misc_control->add_checkbox( "Randomize bookmarks", &mRandomBookmarks, mIdRandomBookmarks, gluiCallbackWrapper );
- glui_window_misc_control->set_main_gfx_window( mAppWindow );
- glui_window_misc_control->add_column( true );
-
- mIdDisableTimeout = start_id++;
- mDisableTimeout = 0;
- glui_window_misc_control->add_checkbox( "Disable plugin timeout", &mDisableTimeout, mIdDisableTimeout, gluiCallbackWrapper );
- glui_window_misc_control->set_main_gfx_window( mAppWindow );
- glui_window_misc_control->add_column( true );
-
- mIdUsePluginReadThread = start_id++;
- mUsePluginReadThread = 0;
- glui_window_misc_control->add_checkbox( "Use plugin read thread", &mUsePluginReadThread, mIdUsePluginReadThread, gluiCallbackWrapper );
- glui_window_misc_control->set_main_gfx_window( mAppWindow );
- glui_window_misc_control->add_column( true );
-
- mIdLargePanelSpacing = start_id++;
- mLargePanelSpacing = 0;
- glui_window_misc_control->add_checkbox( "Large Panel Spacing", &mLargePanelSpacing, mIdLargePanelSpacing, gluiCallbackWrapper );
- glui_window_misc_control->set_main_gfx_window( mAppWindow );
- glui_window_misc_control->add_column( true );
-*/
- // bottom window - status
- mBottomGLUIWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_BOTTOM );
- mStatusText = mBottomGLUIWindow->add_statictext( "" );
- mBottomGLUIWindow->set_main_gfx_window( mAppWindow );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::resetView()
-{
- mViewRotationCtrl->reset();
-
- mViewScaleCtrl->set_x( 0.0f );
- mViewScaleCtrl->set_y( 0.0f );
- mViewScaleCtrl->set_z( 1.3f );
-
- mViewTranslationCtrl->set_x( 0.0f );
- mViewTranslationCtrl->set_y( 0.0f );
- mViewTranslationCtrl->set_z( 0.0f );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::makePickTexture( int id, GLuint* texture_handle, unsigned char** texture_pixels )
-{
- int pick_texture_width = 1024;
- int pick_texture_height = 1024;
- int pick_texture_depth = 3;
- unsigned char* ptr = new unsigned char[ pick_texture_width * pick_texture_height * pick_texture_depth ];
- for( int y = 0; y < pick_texture_height; ++y )
- {
- for( int x = 0; x < pick_texture_width * pick_texture_depth ; x += pick_texture_depth )
- {
- unsigned long bits = 0L;
- bits |= ( id << 20 ) | ( y << 10 ) | ( x / 3 );
- unsigned char r_component = ( bits >> 16 ) & 0xff;
- unsigned char g_component = ( bits >> 8 ) & 0xff;
- unsigned char b_component = bits & 0xff;
-
- ptr[ y * pick_texture_width * pick_texture_depth + x + 0 ] = r_component;
- ptr[ y * pick_texture_width * pick_texture_depth + x + 1 ] = g_component;
- ptr[ y * pick_texture_width * pick_texture_depth + x + 2 ] = b_component;
- };
- };
-
- glGenTextures( 1, texture_handle );
-
- checkGLError("glGenTextures");
- std::cout << "glGenTextures returned " << *texture_handle << std::endl;
-
- bindTexture( *texture_handle );
- glTexImage2D( GL_TEXTURE_2D, 0,
- GL_RGB,
- pick_texture_width, pick_texture_height,
- 0, GL_RGB, GL_UNSIGNED_BYTE, ptr );
-
- *texture_pixels = ptr;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-std::string LLFBConnectTest::mimeTypeFromUrl( std::string& url )
-{
- // default to web
- std::string mime_type = "text/html";
-
- // we may need a more advanced MIME type accessor later :-)
- if ( url.find( ".mov" ) != std::string::npos ) // Movies
- mime_type = "video/quicktime";
- else
- if ( url.find( ".txt" ) != std::string::npos ) // Apple Text descriptors
- mime_type = "video/quicktime";
- else
- if ( url.find( ".mp3" ) != std::string::npos ) // Apple Text descriptors
- mime_type = "video/quicktime";
- else
- if ( url.find( "example://" ) != std::string::npos ) // Example plugin
- mime_type = "example/example";
-
- return mime_type;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-std::string LLFBConnectTest::pluginNameFromMimeType( std::string& mime_type )
-{
-#if LL_DARWIN
- std::string plugin_name( "media_plugin_null.dylib" );
- if ( mime_type == "video/quicktime" )
- plugin_name = "media_plugin_quicktime.dylib";
- else
- if ( mime_type == "text/html" )
- plugin_name = "media_plugin_webkit.dylib";
-
-#elif LL_WINDOWS
- std::string plugin_name( "media_plugin_null.dll" );
-
- if ( mime_type == "video/quicktime" )
- plugin_name = "media_plugin_quicktime.dll";
- else
- if ( mime_type == "text/html" )
- plugin_name = "media_plugin_webkit.dll";
- else
- if ( mime_type == "example/example" )
- plugin_name = "media_plugin_example.dll";
-
-#elif LL_LINUX
- std::string plugin_name( "libmedia_plugin_null.so" );
-
- if ( mime_type == "video/quicktime" )
- plugin_name = "libmedia_plugin_quicktime.so";
- else
- if ( mime_type == "text/html" )
- plugin_name = "libmedia_plugin_webkit.so";
-#endif
- return plugin_name;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-mediaPanel* LLFBConnectTest::addMediaPanel( std::string url )
-{
- // Get the plugin filename using the URL
- std::string mime_type = mimeTypeFromUrl( url );
- std::string plugin_name = pluginNameFromMimeType( mime_type );
-
- // create a random size for the new media
- int media_width;
- int media_height;
- getRandomMediaSize( media_width, media_height, mime_type );
- media_width = 1024;
- media_height = 1536;
-
- // make a new plugin
- LLPluginClassMedia* media_source = new LLPluginClassMedia(this);
-
- // enable cookies so the FB login works
- media_source->enable_cookies(true);
-
- // tell the plugin what size we asked for
- media_source->setSize( media_width, media_height );
-
- // Use the launcher start and initialize the plugin
-#if LL_DARWIN || LL_LINUX
- std::string launcher_name( "SLPlugin" );
-#elif LL_WINDOWS
- std::string launcher_name( "SLPlugin.exe" );
-#endif
-
- // for this test app, use the cwd as the user data path (ugh).
-#if LL_WINDOWS
- std::string user_data_path = ".\\";
-#else
- char cwd[ FILENAME_MAX ];
- if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
- {
- std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl;
- return NULL;
- }
- std::string user_data_path = std::string( cwd ) + "/";
-#endif
- media_source->setUserDataPath(user_data_path);
- media_source->init( launcher_name, user_data_path, plugin_name, false );
- //media_source->setDisableTimeout(mDisableTimeout);
-
- // make a new panel and save parameters
- mediaPanel* panel = new mediaPanel;
- panel->mMediaSource = media_source;
- panel->mStartUrl = url;
- panel->mMimeType = mime_type;
- panel->mMediaWidth = media_width;
- panel->mMediaHeight = media_height;
- panel->mTextureWidth = 0;
- panel->mTextureHeight = 0;
- panel->mTextureScaleX = 0;
- panel->mTextureScaleY = 0;
- panel->mMediaTextureHandle = 0;
- panel->mPickTextureHandle = 0;
- panel->mAppTextureCoordsOpenGL = false; // really need an 'undefined' state here too
- panel->mReadyToRender = false;
-
- // look through current media panels to find an unused index number
- bool id_exists = true;
- for( int nid = 0; nid < mMaxPanels; ++nid )
- {
- // does this id exist already?
- id_exists = false;
- for( int pid = 0; pid < (int)mMediaPanels.size(); ++pid )
- {
- if ( nid == mMediaPanels[ pid ]->mId )
- {
- id_exists = true;
- break;
- };
- };
-
- // id wasn't found so we can use it
- if ( ! id_exists )
- {
- panel->mId = nid;
- break;
- };
- };
-
- // if we get here and this flag is set, there is no room for any more panels
- if ( id_exists )
- {
- std::cout << "No room for any more panels" << std::endl;
- }
- else
- {
- // now we have the ID we can use it to make the
- // pick texture (id is baked into texture pixels)
- makePickTexture( panel->mId, &panel->mPickTextureHandle, &panel->mPickTexturePixels );
-
- // save this in the list of panels
- mMediaPanels.push_back( panel );
-
- // select the panel that was just created
- selectPanel( panel );
-
- // load and start the URL
- panel->mMediaSource->loadURI( url );
- panel->mMediaSource->start();
-
- std::cout << "Adding new media panel for " << url << "(" << media_width << "x" << media_height << ") with index " << panel->mId << " - total panels = " << mMediaPanels.size() << std::endl;
- }
-
- return panel;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::updateMediaPanel( mediaPanel* panel )
-{
-// checkGLError("LLFBConnectTest::updateMediaPanel");
-
- if ( ! panel )
- return;
-
- if(!panel->mMediaSource || !panel->mMediaSource->textureValid())
- {
- panel->mReadyToRender = false;
- return;
- }
-
- // take a reference copy of the plugin values since they
- // might change during this lifetime of this function
- int plugin_media_width = panel->mMediaSource->getWidth();
- int plugin_media_height = panel->mMediaSource->getHeight();
- int plugin_texture_width = panel->mMediaSource->getBitsWidth();
- int plugin_texture_height = panel->mMediaSource->getBitsHeight();
-
- // If the texture isn't created or the media or texture dimensions changed AND
- // the sizes are valid then we need to delete the old media texture (if necessary)
- // then make a new one.
- if ((panel->mMediaTextureHandle == 0 ||
- panel->mMediaWidth != plugin_media_width ||
- panel->mMediaHeight != plugin_media_height ||
- panel->mTextureWidth != plugin_texture_width ||
- panel->mTextureHeight != plugin_texture_height) &&
- ( plugin_media_width > 0 && plugin_media_height > 0 &&
- plugin_texture_width > 0 && plugin_texture_height > 0 ) )
- {
- std::cout << "Valid media size (" << plugin_media_width << " x " << plugin_media_height
- << ") and texture size (" << plugin_texture_width << " x " << plugin_texture_height
- << ") for panel with ID=" << panel->mId << " - making texture" << std::endl;
-
- // delete old GL texture
- if ( isTexture( panel->mMediaTextureHandle ) )
- {
- std::cerr << "updateMediaPanel: deleting texture " << panel->mMediaTextureHandle << std::endl;
- glDeleteTextures( 1, &panel->mMediaTextureHandle );
- panel->mMediaTextureHandle = 0;
- }
-
- std::cerr << "before: pick texture is " << panel->mPickTextureHandle << ", media texture is " << panel->mMediaTextureHandle << std::endl;
-
- // make a GL texture based on the dimensions the plugin told us
- GLuint new_texture = 0;
- glGenTextures( 1, &new_texture );
-
- checkGLError("glGenTextures");
-
- std::cout << "glGenTextures returned " << new_texture << std::endl;
-
- panel->mMediaTextureHandle = new_texture;
-
- bindTexture( panel->mMediaTextureHandle );
-
- std::cout << "Setting texture size to " << plugin_texture_width << " x " << plugin_texture_height << std::endl;
- glTexImage2D( GL_TEXTURE_2D, 0,
- GL_RGB,
- plugin_texture_width, plugin_texture_height,
- 0, GL_RGB, GL_UNSIGNED_BYTE,
- 0 );
-
-
- std::cerr << "after: pick texture is " << panel->mPickTextureHandle << ", media texture is " << panel->mMediaTextureHandle << std::endl;
- };
-
- // update our record of the media and texture dimensions
- // NOTE: do this after we we check for sizes changes
- panel->mMediaWidth = plugin_media_width;
- panel->mMediaHeight = plugin_media_height;
- panel->mTextureWidth = plugin_texture_width;
- panel->mTextureHeight = plugin_texture_height;
- if ( plugin_texture_width > 0 )
- {
- panel->mTextureScaleX = (double)panel->mMediaWidth / (double)panel->mTextureWidth;
- };
- if ( plugin_texture_height > 0 )
- {
- panel->mTextureScaleY = (double)panel->mMediaHeight / (double)panel->mTextureHeight;
- };
-
- // update the flag which tells us if the media source uses OprnGL coords or not.
- panel->mAppTextureCoordsOpenGL = panel->mMediaSource->getTextureCoordsOpenGL();
-
- // Check to see if we have enough to render this panel.
- // If we do, set a flag that the display functions use so
- // they only render a panel with media if it's ready.
- if ( panel->mMediaWidth < 0 ||
- panel->mMediaHeight < 0 ||
- panel->mTextureWidth < 1 ||
- panel->mTextureHeight < 1 ||
- panel->mMediaTextureHandle == 0 )
- {
- panel->mReadyToRender = false;
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-mediaPanel* LLFBConnectTest::replaceMediaPanel( mediaPanel* panel, std::string url )
-{
- // no media panels so we can't change anything - have to add
- if ( mMediaPanels.size() == 0 )
- return NULL;
-
- // sanity check
- if ( ! panel )
- return NULL;
-
- int index;
- for(index = 0; index < (int)mMediaPanels.size(); index++)
- {
- if(mMediaPanels[index] == panel)
- break;
- }
-
- if(index >= (int)mMediaPanels.size())
- {
- // panel isn't in mMediaPanels
- return NULL;
- }
-
- std::cout << "Replacing media panel with index " << panel->mId << std::endl;
-
- int panel_id = panel->mId;
-
- if(mSelectedPanel == panel)
- mSelectedPanel = NULL;
-
- delete panel;
-
- // Get the plugin filename using the URL
- std::string mime_type = mimeTypeFromUrl( url );
- std::string plugin_name = pluginNameFromMimeType( mime_type );
-
- // create a random size for the new media
- int media_width;
- int media_height;
- getRandomMediaSize( media_width, media_height, mime_type );
-
- // make a new plugin
- LLPluginClassMedia* media_source = new LLPluginClassMedia(this);
-
- // tell the plugin what size we asked for
- media_source->setSize( media_width, media_height );
-
- // Use the launcher start and initialize the plugin
-#if LL_DARWIN || LL_LINUX
- std::string launcher_name( "SLPlugin" );
-#elif LL_WINDOWS
- std::string launcher_name( "SLPlugin.exe" );
-#endif
-
- // for this test app, use the cwd as the user data path (ugh).
-#if LL_WINDOWS
- std::string user_data_path = ".\\";
-#else
- char cwd[ FILENAME_MAX ];
- if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
- {
- std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl;
- return NULL;
- }
- std::string user_data_path = std::string( cwd ) + "/";
-#endif
-
- media_source->setUserDataPath(user_data_path);
- media_source->init( launcher_name, user_data_path, plugin_name, false );
- //media_source->setDisableTimeout(mDisableTimeout);
-
- // make a new panel and save parameters
- panel = new mediaPanel;
- panel->mMediaSource = media_source;
- panel->mStartUrl = url;
- panel->mMimeType = mime_type;
- panel->mMediaWidth = media_width;
- panel->mMediaHeight = media_height;
- panel->mTextureWidth = 0;
- panel->mTextureHeight = 0;
- panel->mTextureScaleX = 0;
- panel->mTextureScaleY = 0;
- panel->mMediaTextureHandle = 0;
- panel->mPickTextureHandle = 0;
- panel->mAppTextureCoordsOpenGL = false; // really need an 'undefined' state here too
- panel->mReadyToRender = false;
-
- panel->mId = panel_id;
-
- // Replace the entry in the panels array
- mMediaPanels[index] = panel;
-
- // now we have the ID we can use it to make the
- // pick texture (id is baked into texture pixels)
- makePickTexture( panel->mId, &panel->mPickTextureHandle, &panel->mPickTexturePixels );
-
- // select the panel that was just created
- selectPanel( panel );
-
- // load and start the URL
- panel->mMediaSource->loadURI( url );
- panel->mMediaSource->start();
-
- return panel;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::getRandomMediaSize( int& width, int& height, std::string mime_type )
-{
- // Make a new media source with a random size which we'll either
- // directly or the media plugin will tell us what it wants later.
- // Use a random size so we can test support for weird media sizes.
- // (Almost everything else will get filled in later once the
- // plugin responds)
- // NB. Do we need to enforce that width is on 4 pixel boundary?
- width = ( ( rand() % 170 ) + 30 ) * 4;
- height = ( ( rand() % 170 ) + 30 ) * 4;
-
- // adjust this random size if it's a browser so we get
- // a more useful size for testing..
- if ( mime_type == "text/html" || mime_type == "example/example" )
- {
- width = ( ( rand() % 100 ) + 100 ) * 4;
- height = ( width * ( ( rand() % 400 ) + 1000 ) ) / 1000;
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::remMediaPanel( mediaPanel* panel )
-{
- // always leave one panel
- if ( mMediaPanels.size() == 1 )
- return;
-
- // sanity check - don't think this can happen but see above for a case where it might...
- if ( ! panel )
- return;
-
- std::cout << "Removing media panel with index " << panel->mId << " - total panels = " << mMediaPanels.size() - 1 << std::endl;
-
- if(mSelectedPanel == panel)
- mSelectedPanel = NULL;
-
- delete panel;
-
- // remove from storage list
- for( int i = 0; i < (int)mMediaPanels.size(); ++i )
- {
- if ( mMediaPanels[ i ] == panel )
- {
- mMediaPanels.erase( mMediaPanels.begin() + i );
- break;
- };
- };
-
- // select the first panel
- selectPanel( mMediaPanels[ 0 ] );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::updateStatusBar()
-{
- if ( ! mSelectedPanel )
- return;
-
- // cache results - this is a very slow function
- static int cached_id = -1;
- static int cached_media_width = -1;
- static int cached_media_height = -1;
- static int cached_texture_width = -1;
- static int cached_texture_height = -1;
- static bool cached_supports_browser_media = true;
- static bool cached_supports_time_media = false;
- static int cached_movie_time = -1;
- static GLfloat cached_distance = -1.0f;
-
- static std::string cached_plugin_version = "";
- if (
- cached_id == mSelectedPanel->mId &&
- cached_media_width == mSelectedPanel->mMediaWidth &&
- cached_media_height == mSelectedPanel->mMediaHeight &&
- cached_texture_width == mSelectedPanel->mTextureWidth &&
- cached_texture_height == mSelectedPanel->mTextureHeight &&
- cached_supports_browser_media == mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() &&
- cached_supports_time_media == mSelectedPanel->mMediaSource->pluginSupportsMediaTime() &&
- cached_plugin_version == mSelectedPanel->mMediaSource->getPluginVersion() &&
- cached_movie_time == (int)mSelectedPanel->mMediaSource->getCurrentTime() &&
- cached_distance == mDistanceCameraToSelectedGeometry
- )
- {
- // nothing changed so don't spend time here
- return;
- };
-
- std::ostringstream stream( "" );
-
- stream.str( "" );
- stream.clear();
-
- stream << "Id: ";
- stream << std::setw( 2 ) << std::setfill( '0' );
- stream << mSelectedPanel->mId;
- stream << " | ";
- stream << "Media: ";
- stream << std::setw( 3 ) << std::setfill( '0' );
- stream << mSelectedPanel->mMediaWidth;
- stream << " x ";
- stream << std::setw( 3 ) << std::setfill( '0' );
- stream << mSelectedPanel->mMediaHeight;
- stream << " | ";
- stream << "Texture: ";
- stream << std::setw( 4 ) << std::setfill( '0' );
- stream << mSelectedPanel->mTextureWidth;
- stream << " x ";
- stream << std::setw( 4 ) << std::setfill( '0' );
- stream << mSelectedPanel->mTextureHeight;
-
- stream << " | ";
- stream << "Distance: ";
- stream << std::setw( 6 );
- stream << std::setprecision( 3 );
- stream << std::setprecision( 3 );
- stream << mDistanceCameraToSelectedGeometry;
- stream << " | ";
-
- if ( mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() )
- stream << "BROWSER";
- else
- if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() )
- stream << "TIME ";
- stream << " | ";
- stream << mSelectedPanel->mMediaSource->getPluginVersion();
- stream << " | ";
- if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() )
- {
- stream << std::setw( 3 ) << std::setfill( '0' );
- stream << (int)mSelectedPanel->mMediaSource->getCurrentTime();
- stream << " / ";
- stream << std::setw( 3 ) << std::setfill( '0' );
- stream << (int)mSelectedPanel->mMediaSource->getDuration();
- stream << " @ ";
- stream << (int)mSelectedPanel->mMediaSource->getCurrentPlayRate();
- stream << " | ";
- };
-
- glutSetWindow( mBottomGLUIWindow->get_glut_window_id() );
- mStatusText->set_text( const_cast< char*>( stream.str().c_str() ) );
- glutSetWindow( mAppWindow );
-
- // caching
- cached_id = mSelectedPanel->mId;
- cached_media_width = mSelectedPanel->mMediaWidth;
- cached_media_height = mSelectedPanel->mMediaHeight;
- cached_texture_width = mSelectedPanel->mTextureWidth;
- cached_texture_height = mSelectedPanel->mTextureHeight;
- cached_supports_browser_media = mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser();
- cached_supports_time_media = mSelectedPanel->mMediaSource->pluginSupportsMediaTime();
- cached_plugin_version = mSelectedPanel->mMediaSource->getPluginVersion();
- cached_movie_time = (int)mSelectedPanel->mMediaSource->getCurrentTime();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::dumpPanelInfo()
-{
- std::cout << std::endl << "===== Media Panels =====" << std::endl;
- for( int i = 0; i < (int)mMediaPanels.size(); ++i )
- {
- std::cout << std::setw( 2 ) << std::setfill( '0' );
- std::cout << i + 1 << "> ";
- std::cout << "Id: ";
- std::cout << std::setw( 2 ) << std::setfill( '0' );
- std::cout << mMediaPanels[ i ]->mId;
- std::cout << " | ";
- std::cout << "Media: ";
- std::cout << std::setw( 3 ) << std::setfill( '0' );
- std::cout << mMediaPanels[ i ]->mMediaWidth;
- std::cout << " x ";
- std::cout << std::setw( 3 ) << std::setfill( '0' );
- std::cout << mMediaPanels[ i ]->mMediaHeight;
- std::cout << " | ";
- std::cout << "Texture: ";
- std::cout << std::setw( 4 ) << std::setfill( '0' );
- std::cout << mMediaPanels[ i ]->mTextureWidth;
- std::cout << " x ";
- std::cout << std::setw( 4 ) << std::setfill( '0' );
- std::cout << mMediaPanels[ i ]->mTextureHeight;
- std::cout << " | ";
- if ( mMediaPanels[ i ] == mSelectedPanel )
- std::cout << "(selected)";
-
- std::cout << std::endl;
- };
- std::cout << "========================" << std::endl;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLFBConnectTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
-{
- // Uncomment this to make things much, much quieter.
-// return;
-
- switch(event)
- {
- case MEDIA_EVENT_CONTENT_UPDATED:
- // too spammy -- don't log these
-// std::cerr << "Media event: MEDIA_EVENT_CONTENT_UPDATED " << std::endl;
- break;
-
- case MEDIA_EVENT_TIME_DURATION_UPDATED:
- // too spammy -- don't log these
-// std::cerr << "Media event: MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << std::endl;
- break;
-
- case MEDIA_EVENT_SIZE_CHANGED:
- std::cerr << "Media event: MEDIA_EVENT_SIZE_CHANGED " << std::endl;
- break;
-
- case MEDIA_EVENT_CURSOR_CHANGED:
- std::cerr << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << std::endl;
- break;
-
- case MEDIA_EVENT_NAVIGATE_BEGIN:
- std::cerr << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN " << std::endl;
- break;
-
- case MEDIA_EVENT_NAVIGATE_COMPLETE:
- std::cerr << "Media event: MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << std::endl;
- break;
-
- case MEDIA_EVENT_PROGRESS_UPDATED:
- std::cerr << "Media event: MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << std::endl;
- break;
-
- case MEDIA_EVENT_STATUS_TEXT_CHANGED:
- std::cerr << "Media event: MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << std::endl;
- break;
-
- case MEDIA_EVENT_NAME_CHANGED:
- std::cerr << "Media event: MEDIA_EVENT_NAME_CHANGED, new name is: " << self->getMediaName() << std::endl;
- glutSetWindowTitle( self->getMediaName().c_str() );
- break;
-
- case MEDIA_EVENT_LOCATION_CHANGED:
- {
- std::cerr << "Media event: MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << std::endl;
- mediaPanel* panel = findMediaPanel(self);
- if(panel != NULL)
- {
- panel->mStartUrl = self->getLocation();
- if(panel == mSelectedPanel)
- {
- mUrlEdit->set_text(const_cast<char*>(panel->mStartUrl.c_str()) );
- }
- }
- }
- break;
-
- case MEDIA_EVENT_NAVIGATE_ERROR_PAGE:
- std::cerr << "Media event: MEDIA_EVENT_NAVIGATE_ERROR_PAGE, uri is: " << self->getClickURL() << std::endl;
- break;
-
- case MEDIA_EVENT_CLICK_LINK_HREF:
- {
- std::cerr << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, uri is " << self->getClickURL() << ", target is " << self->getClickTarget() << std::endl;
- // retrieve the event parameters
- std::string url = self->getClickURL();
- std::string target = self->getClickTarget();
-
- if(target == "_external")
- {
- // this should open in an external browser, but since this is a test app we don't care.
- }
- else if(target == "_blank")
- {
- // Create a new panel with the specified URL.
- addMediaPanel(url);
- }
- else // other named target
- {
- mediaPanel *target_panel = findMediaPanel(target);
- if(target_panel)
- {
- target_panel = replaceMediaPanel(target_panel, url);
- }
- else
- {
- target_panel = addMediaPanel(url);
- }
-
- if(target_panel)
- {
- target_panel->mTarget = target;
- }
- }
- }
- break;
-
- case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
- std::cerr << "Media event: MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << std::endl;
- break;
-
- case MEDIA_EVENT_PLUGIN_FAILED:
- std::cerr << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << std::endl;
- break;
-
- case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
- std::cerr << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << std::endl;
- break;
-
- case MEDIA_EVENT_CLOSE_REQUEST:
- std::cerr << "Media event: MEDIA_EVENT_CLOSE_REQUEST" << std::endl;
- break;
-
- case MEDIA_EVENT_PICK_FILE_REQUEST:
- std::cerr << "Media event: MEDIA_EVENT_PICK_FILE_REQUEST" << std::endl;
- // TODO: display an actual file picker
- self->sendPickFileResponse("cake");
- break;
-
- case MEDIA_EVENT_GEOMETRY_CHANGE:
- std::cerr << "Media event: MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID()
- << ", x = " << self->getGeometryX()
- << ", y = " << self->getGeometryY()
- << ", width = " << self->getGeometryWidth()
- << ", height = " << self->getGeometryHeight()
- << std::endl;
- break;
-
- case MEDIA_EVENT_AUTH_REQUEST:
- {
- //std::cerr << "Media event: MEDIA_EVENT_AUTH_REQUEST, url " << self->getAuthURL() ", realm " << self->getAuthRealm() << std::endl;
-
- // TODO: display an auth dialog
- self->sendAuthResponse(false, "", "");
- }
- break;
-
- case MEDIA_EVENT_LINK_HOVERED:
- {
- std::cerr << "Media event: MEDIA_EVENT_LINK_HOVERED, hover text is: " << self->getHoverText() << std::endl;
- }
- break;
-
- default:
- {
- std::cerr << "Media event: <unknown>, code is: " << int(event) << std::endl;
- }
- break;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-static void gluiCallbackWrapper( int control_id )
-{
- if ( gApplication )
- gApplication->gluiCallback( control_id );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void glutReshape( int width, int height )
-{
- if ( gApplication )
- gApplication->reshape( width, height );
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void glutDisplay()
-{
- if ( gApplication )
- gApplication->display();
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void glutIdle(int update_ms)
-{
- GLUI_Master.set_glutTimerFunc( update_ms, glutIdle, update_ms);
-
- if ( gApplication )
- gApplication->idle();
-
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void glutKeyboard( unsigned char key, int x, int y )
-{
- if ( gApplication )
- gApplication->keyboard( key );
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void glutMousePassive( int x, int y )
-{
- if ( gApplication )
- gApplication->mousePassive( x, y );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void glutMouseMove( int x , int y )
-{
- if ( gApplication )
- gApplication->mouseMove( x, y );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void glutMouseButton( int button, int state, int x, int y )
-{
- if ( gApplication )
- gApplication->mouseButton( button, state, x, y );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-int main( int argc, char* argv[] )
-{
-#if LL_DARWIN
- // Set the current working directory to <application bundle>/Contents/Resources/
- CFURLRef resources_url = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
- if(resources_url != NULL)
- {
- CFStringRef resources_string = CFURLCopyFileSystemPath(resources_url, kCFURLPOSIXPathStyle);
- CFRelease(resources_url);
- if(resources_string != NULL)
- {
- char buffer[PATH_MAX] = "";
- if(CFStringGetCString(resources_string, buffer, sizeof(buffer), kCFStringEncodingUTF8))
- {
- chdir(buffer);
- }
- CFRelease(resources_string);
- }
- }
-#endif
-
- glutInit( &argc, argv );
- glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB );
-
- const int app_window_x = 80;
- const int app_window_y = 0;
- const int app_window_width = 960;
- const int app_window_height = 960;
-
- glutInitWindowPosition( app_window_x, app_window_y );
- glutInitWindowSize( app_window_width, app_window_height );
-
- int app_window_handle = glutCreateWindow( "LLFBConnectTest" );
-
- glutDisplayFunc( glutDisplay );
-
- GLUI_Master.set_glutReshapeFunc( glutReshape );
- GLUI_Master.set_glutKeyboardFunc( glutKeyboard );
- GLUI_Master.set_glutMouseFunc( glutMouseButton );
-
- glutPassiveMotionFunc( glutMousePassive );
- glutMotionFunc( glutMouseMove );
-
- glutSetWindow( app_window_handle );
-
- gApplication = new LLFBConnectTest( app_window_handle, app_window_width, app_window_height );
-
- // update at approximately 60hz
- int update_ms = 1000 / 60;
-
- GLUI_Master.set_glutTimerFunc( update_ms, glutIdle, update_ms);
-
- glutMainLoop();
-
- delete gApplication;
-}
diff --git a/indra/test_apps/llfbconnecttest/llfbconnecttest.h b/indra/test_apps/llfbconnecttest/llfbconnecttest.h
deleted file mode 100644
index 77e4d096d0..0000000000
--- a/indra/test_apps/llfbconnecttest/llfbconnecttest.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/**
- * @file LLFBConnectTest.cpp
- * @brief Facebook Connect Test App
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_FB_CONNECT_H
-#define LL_FB_CONNECT_H
-
-#include <vector>
-#include <string>
-#include "llpluginclassmedia.h"
-#include "llgl.h"
-
-// Forward declarations
-class GLUI_Rotation;
-class GLUI_Translation;
-class GLUI_Listbox;
-class GLUI_EditText;
-class GLUI_StaticText;
-class GLUI;
-class GLUI_Button;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-struct mediaPanel
-{
- public:
- mediaPanel();
- ~mediaPanel();
- int mId;
- std::string mStartUrl;
- std::string mMimeType;
- std::string mTarget;
- LLPluginClassMedia *mMediaSource;
- int mMediaWidth;
- int mMediaHeight;
- int mTextureWidth;
- int mTextureHeight;
- double mTextureScaleX;
- double mTextureScaleY;
- GLuint mMediaTextureHandle;
- GLuint mPickTextureHandle;
- unsigned char* mPickTexturePixels;
- bool mAppTextureCoordsOpenGL;
- bool mReadyToRender;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-class LLFBConnectTest : public LLPluginClassMediaOwner
-{
- public:
- LLFBConnectTest( int app_window, int window_width, int window_height );
- ~LLFBConnectTest();
-
- void reshape( int width, int height );
- void display();
- void idle();
- void gluiCallback( int control_id );
- void keyboard( int key );
- void mousePassive( int x, int y );
- void mouseButton( int button, int state, int x, int y );
- void mouseMove( int x, int y );
-
- void bindTexture(GLuint texture, GLint row_length = 0, GLint alignment = 1);
- bool checkGLError(const char *name = "OpenGL");
- void drawGeometry( int panel, bool selected );
- void startPanelHighlight( float red, float green, float blue, float line_width );
- void endPanelHighlight();
- enum { DrawTypePickTexture, DrawTypeMediaTexture };
- void draw( int draw_type );
- void windowPosToTexturePos( int window_x, int window_y, int& media_x, int& media_y, int& id );
-
- mediaPanel* addMediaPanel( std::string url );
- void updateMediaPanel( mediaPanel* panel );
- void remMediaPanel( mediaPanel* panel );
- mediaPanel* replaceMediaPanel( mediaPanel* panel, std::string url );
- void getRandomMediaSize( int& width, int& height, std::string mime_type );
- void navigateToNewURI( std::string uri );
- void initUrlHistory( std::string uri );
- void selectPanelById( int id );
- void selectPanel( mediaPanel* panel );
- mediaPanel* findMediaPanel( LLPluginClassMedia* panel );
- mediaPanel* findMediaPanel( const std::string &target_name );
- void makePickTexture( int id, GLuint* texture_handle, unsigned char** texture_pixels );
- void makeChrome();
- void resetView();
-
- void dumpPanelInfo();
- void updateStatusBar();
-
- GLfloat distanceToCamera( GLfloat point_x, GLfloat point_y, GLfloat point_z );
-
-
- // Inherited from LLPluginClassMediaOwner
- /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent);
-
- private:
- const int mVersionMajor;
- const int mVersionMinor;
- const int mVersionPatch;
- const int mMaxPanels;
- int mAppWindow;
- int mWindowWidth;
- int mWindowHeight;
- int mCurMouseX;
- int mCurMouseY;
- unsigned char mPixelReadColor[ 3 ];
- bool mFuzzyMedia;
- const std::string mHomeWebUrl;
-
- std::vector< mediaPanel* > mMediaPanels;
- mediaPanel* mSelectedPanel;
- std::string mimeTypeFromUrl( std::string& url );
- std::string pluginNameFromMimeType( std::string& mime_type );
-
- GLUI_Rotation* mViewRotationCtrl;
- GLUI_Translation* mViewScaleCtrl;
- GLUI_Translation* mViewTranslationCtrl;
- float mViewportAspect;
- float mViewPos[ 3 ];
- float mViewRotation[ 16 ];
-
- float mDistanceCameraToSelectedGeometry;
-
- std::vector< std::pair< std::string, std::string > > mBookmarks;
- GLUI_Listbox* mBookmarkList;
- int mIdBookmarks;
- int mIdUrlEdit;
- GLUI_EditText* mUrlEdit;
- int mSelBookmark;
-
- int mIdControlExitApp;
-
- GLUI* mGluiMediaBrowserControlWindow;
- int mIdMediaBrowserControlBack;
- GLUI_Button* mMediaBrowserControlBackButton;
- int mIdMediaBrowserControlStop;
- int mIdMediaBrowserControlForward;
- GLUI_Button* mMediaBrowserControlForwardButton;
- bool mGluiMediaBrowserControlWindowFlag;
- bool mMediaBrowserControlBackButtonFlag;
- bool mMediaBrowserControlForwardButtonFlag;
- int mIdMediaBrowserControlHome;
- int mIdMediaBrowserControlReload;
-
- GLUI* mBottomGLUIWindow;
- GLUI_StaticText* mStatusText;
-};
-
-#endif // LL_FB_CONNECT_H
-
diff --git a/indra/test_apps/llplugintest/CMakeLists.txt b/indra/test_apps/llplugintest/CMakeLists.txt
index 0c8bdc464d..e682eaccca 100755
--- a/indra/test_apps/llplugintest/CMakeLists.txt
+++ b/indra/test_apps/llplugintest/CMakeLists.txt
@@ -254,138 +254,8 @@ endif (DARWIN)
# )
#endif (DARWIN)
-### llmediaplugintest
-
-set(llmediaplugintest_SOURCE_FILES
- llmediaplugintest.cpp
- llmediaplugintest.h
- bookmarks.txt
- )
-
-add_executable(llmediaplugintest
- WIN32
- MACOSX_BUNDLE
- ${llmediaplugintest_SOURCE_FILES}
-)
-
-set_target_properties(llmediaplugintest
- PROPERTIES
- WIN32_EXECUTABLE
- FALSE
-)
-
-target_link_libraries(llmediaplugintest
- ${GLUT_LIBRARY}
- ${GLUI_LIBRARY}
- ${OPENGL_LIBRARIES}
- ${LLPLUGIN_LIBRARIES}
- ${LLMESSAGE_LIBRARIES}
- ${LLCOMMON_LIBRARIES}
- ${PLUGIN_API_WINDOWS_LIBRARIES}
-)
-
-if (DARWIN)
- # The testbed needs to use a couple of CoreFoundation calls now, to deal with being a bundled app.
- target_link_libraries(llmediaplugintest
- ${COREFOUNDATION_LIBRARY}
- )
-endif (DARWIN)
-
-add_dependencies(llmediaplugintest
- stage_third_party_libs
- SLPlugin
- media_plugin_quicktime
- media_plugin_webkit
- media_plugin_example
- ${LLPLUGIN_LIBRARIES}
- ${LLMESSAGE_LIBRARIES}
- ${LLCOMMON_LIBRARIES}
-)
-
-# turn off weird GLUI pragma
-add_definitions(-DGLUI_NO_LIB_PRAGMA)
-
-if (DARWIN OR LINUX)
- # glui.h contains code that triggers the "overloaded-virtual" warning in gcc.
- set_source_files_properties(llmediaplugintest.cpp PROPERTIES COMPILE_FLAGS "-Wno-overloaded-virtual")
-endif (DARWIN OR LINUX)
-
# Gather build products of the various dependencies into the build directory for the testbed.
-if (DARWIN)
- # path inside the app bundle where we'll need to copy plugins and other related files
- set(PLUGINS_DESTINATION_DIR
- ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llmediaplugintest.app/Contents/Resources
- )
-
- # create the Contents/Resources directory
- add_custom_command(
- TARGET llmediaplugintest POST_BUILD
- COMMAND ${CMAKE_COMMAND}
- ARGS
- -E
- make_directory
- ${PLUGINS_DESTINATION_DIR}
- COMMENT "Creating Resources directory in app bundle."
- )
-else (DARWIN)
- set(PLUGINS_DESTINATION_DIR
- ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
- )
-endif (DARWIN)
-
-set(BUILT_SLPLUGIN $<TARGET_FILE:SLPlugin>)
-add_custom_command(TARGET llmediaplugintest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_SLPLUGIN} ${PLUGINS_DESTINATION_DIR}
- DEPENDS ${BUILT_SLPLUGIN}
-)
-
-set(BUILT_LLCOMMON $<TARGET_FILE:llcommon>)
-add_custom_command(TARGET llmediaplugintest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_LLCOMMON} ${PLUGINS_DESTINATION_DIR}
- DEPENDS ${BUILT_LLCOMMON}
-)
-
-set(BUILT_WEBKIT_PLUGIN $<TARGET_FILE:media_plugin_webkit>)
-add_custom_command(TARGET llmediaplugintest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_WEBKIT_PLUGIN} ${PLUGINS_DESTINATION_DIR}
- DEPENDS ${BUILT_WEBKIT_PLUGIN}
-)
-
-if (DARWIN OR WINDOWS)
- set(BUILT_QUICKTIME_PLUGIN $<TARGET_FILE:media_plugin_quicktime>)
- add_custom_command(TARGET llmediaplugintest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_QUICKTIME_PLUGIN} ${PLUGINS_DESTINATION_DIR}
- DEPENDS ${BUILT_QUICKTIME_PLUGIN}
- )
-endif (DARWIN OR WINDOWS)
-
-set(BUILT_EXAMPLE_PLUGIN $<TARGET_FILE:media_plugin_example>)
-add_custom_command(TARGET llmediaplugintest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_EXAMPLE_PLUGIN} ${PLUGINS_DESTINATION_DIR}
- DEPENDS ${BUILT_EXAMPLE_PLUGIN}
-)
-
-# copy over bookmarks file if llmediaplugintest gets built
-set(BUILT_LLMEDIAPLUGINTEST $<TARGET_FILE:llmediaplugintest>)
-add_custom_command(TARGET llmediaplugintest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${CMAKE_CURRENT_BINARY_DIR}/
- DEPENDS ${BUILT_LLMEDIAPLUGINTEST}
-)
-
-# also copy it to the same place as SLPlugin, which is what the mac wants...
-add_custom_command(TARGET llmediaplugintest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${PLUGINS_DESTINATION_DIR}
- DEPENDS ${BUILT_LLMEDIAPLUGINTEST}
-)
-
-if (DARWIN)
-# add_custom_command(TARGET llmediaplugintest POST_BUILD
-# COMMAND ${CMAKE_COMMAND} -E copy ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib ${PLUGINS_DESTINATION_DIR}
-# DEPENDS ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib
-# )
-endif (DARWIN)
-
if(WINDOWS)
#********************
# Plugin test library deploy
@@ -398,11 +268,6 @@ if(WINDOWS)
libgmodule-2.0-0.dll
libgobject-2.0-0.dll
libgthread-2.0-0.dll
- qtcored4.dll
- qtguid4.dll
- qtnetworkd4.dll
- qtopengld4.dll
- qtwebkitd4.dll
ssleay32.dll
)
copy_if_different(
@@ -413,40 +278,6 @@ if(WINDOWS)
)
set(plugin_test_targets ${plugin_test_targets} ${out_targets})
- # Debug config runtime files required for the plugin test mule (Qt image format plugins)
- set(plugintest_debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}/imageformats")
- set(plugintest_debug_files
- qgifd4.dll
- qicod4.dll
- qjpegd4.dll
- qmngd4.dll
- qsvgd4.dll
- qtiffd4.dll
- )
- copy_if_different(
- ${plugintest_debug_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/Debug/imageformats"
- out_targets
- ${plugintest_debug_files}
- )
- set(plugin_test_targets ${plugin_test_targets} ${out_targets})
-
- # Debug config runtime files required for the plugin test mule (Qt codec plugins)
- set(plugintest_debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}/codecs")
- set(plugintest_debug_files
- qcncodecsd4.dll
- qjpcodecsd4.dll
- qkrcodecsd4.dll
- qtwcodecsd4.dll
- )
- copy_if_different(
- ${plugintest_debug_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/Debug/codecs"
- out_targets
- ${plugintest_debug_files}
- )
- set(plugin_test_targets ${plugin_test_targets} ${out_targets})
-
# Release & ReleaseDebInfo config runtime files required for the plugin test mule
set(plugintest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
set(plugintest_release_files
@@ -455,12 +286,6 @@ if(WINDOWS)
libgmodule-2.0-0.dll
libgobject-2.0-0.dll
libgthread-2.0-0.dll
- qtcore4.dll
- qtgui4.dll
- qtnetwork4.dll
- qtopengl4.dll
- qtwebkit4.dll
- qtxmlpatterns4.dll
ssleay32.dll
)
copy_if_different(
@@ -479,63 +304,11 @@ if(WINDOWS)
)
set(plugin_test_targets ${plugin_test_targets} ${out_targets})
- # Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt image format plugins)
- set(plugintest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}/imageformats")
- set(plugintest_release_files
- qgif4.dll
- qico4.dll
- qjpeg4.dll
- qmng4.dll
- qsvg4.dll
- qtiff4.dll
- )
- copy_if_different(
- ${plugintest_release_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/Release/imageformats"
- out_targets
- ${plugintest_release_files}
- )
- set(plugin_test_targets ${plugin_test_targets} ${out_targets})
-
- copy_if_different(
- ${plugintest_release_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/imageformats"
- out_targets
- ${plugintest_release_files}
- )
- set(plugin_test_targets ${plugin_test_targets} ${out_targets})
-
- # Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt codec plugins)
- set(plugintest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}/codecs")
- set(plugintest_release_files
- qcncodecs4.dll
- qjpcodecs4.dll
- qkrcodecs4.dll
- qtwcodecs4.dll
- )
- copy_if_different(
- ${plugintest_release_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/Release/codecs"
- out_targets
- ${plugintest_release_files}
- )
- set(plugin_test_targets ${plugin_test_targets} ${out_targets})
-
- copy_if_different(
- ${plugintest_release_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/codecs"
- out_targets
- ${plugintest_release_files}
- )
- set(plugin_test_targets ${plugin_test_targets} ${out_targets})
-
add_custom_target(copy_plugintest_libs ALL
DEPENDS
${plugin_test_targets}
)
- add_dependencies(llmediaplugintest copy_plugintest_libs)
-
endif(WINDOWS)
if (DARWIN)
@@ -545,20 +318,6 @@ if (DARWIN)
libaprutil-1.0.dylib
libapr-1.0.dylib
libexpat.1.5.2.dylib
- libQtCore.4.7.1.dylib
- libQtCore.4.dylib
- libQtGui.4.7.1.dylib
- libQtGui.4.dylib
- libQtNetwork.4.7.1.dylib
- libQtNetwork.4.dylib
- libQtOpenGL.4.7.1.dylib
- libQtOpenGL.4.dylib
- libQtWebKit.4.7.1.dylib
- libQtWebKit.4.dylib
- libQtSvg.4.7.1.dylib
- libQtSvg.4.dylib
- libQtXml.4.7.1.dylib
- libQtXml.4.dylib
)
copy_if_different(
${plugintest_release_src_dir}
@@ -568,46 +327,10 @@ if (DARWIN)
)
set(plugin_test_targets ${plugin_test_targets} ${out_targets})
- # Release & ReleaseDebInfo config runtime files required for the FB connect test (Qt image format plugins)
- set(plugintest_release_src_dir "${ARCH_PREBUILT_DIRS_PLUGINS}/imageformats")
- set(plugintest_release_files
- libqgif.dylib
- libqico.dylib
- libqjpeg.dylib
- libqmng.dylib
- libqsvg.dylib
- libqtiff.dylib
- )
- copy_if_different(
- ${plugintest_release_src_dir}
- "${PLUGINS_DESTINATION_DIR}/imageformats"
- out_targets
- ${plugintest_release_files}
- )
- set(plugin_test_targets ${plugin_test_targets} ${out_targets})
-
- # Release & ReleaseDebInfo config runtime files required for the FB connect test (Qt codec plugins)
- set(plugintest_release_src_dir "${ARCH_PREBUILT_DIRS_PLUGINS}/codecs")
- set(plugintest_release_files
- libqcncodecs.dylib
- libqjpcodecs.dylib
- libqkrcodecs.dylib
- libqtwcodecs.dylib
- )
- copy_if_different(
- ${plugintest_release_src_dir}
- "${PLUGINS_DESTINATION_DIR}/codecs"
- out_targets
- ${plugintest_release_files}
- )
- set(plugin_test_targets ${plugin_test_targets} ${out_targets})
-
add_custom_target(copy_plugintest_libs ALL
DEPENDS
${plugin_test_targets}
)
- add_dependencies(llmediaplugintest copy_plugintest_libs)
endif (DARWIN)
-ll_deploy_sharedlibs_command(llmediaplugintest)
diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp
deleted file mode 100755
index fa4f5abd28..0000000000
--- a/indra/test_apps/llplugintest/llmediaplugintest.cpp
+++ /dev/null
@@ -1,2377 +0,0 @@
-/**
- * @file LLMediaPluginTest.cpp
- * @brief Primary test application for LLMedia (Separate Process) Plugin system
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "indra_constants.h"
-
-#include "llapr.h"
-#include "llerrorcontrol.h"
-
-#include <math.h>
-#include <iomanip>
-#include <sstream>
-#include <ctime>
-
-#include "llmediaplugintest.h"
-
-
-#if LL_WINDOWS
-#pragma warning(disable: 4263)
-#pragma warning(disable: 4264)
-#endif
-
-#if __APPLE__
- #include <GLUT/glut.h>
- #include <CoreFoundation/CoreFoundation.h>
-#else
- #define FREEGLUT_STATIC
- #include "GL/freeglut.h"
- #define GLUI_FREEGLUT
-#endif
-
-#include "glui.h"
-
-
-LLMediaPluginTest* gApplication = 0;
-static void gluiCallbackWrapper( int control_id );
-
-////////////////////////////////////////////////////////////////////////////////
-//
-static bool isTexture( GLuint texture )
-{
- bool result = false;
-
- // glIsTexture will sometimes return false for real textures... do this instead.
- if(texture != 0)
- result = true;
-
- return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-mediaPanel::mediaPanel()
-{
- mMediaTextureHandle = 0;
- mPickTextureHandle = 0;
- mMediaSource = NULL;
- mPickTexturePixels = NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-mediaPanel::~mediaPanel()
-{
- // delete OpenGL texture handles
- if ( isTexture( mPickTextureHandle ) )
- {
- std::cerr << "remMediaPanel: deleting pick texture " << mPickTextureHandle << std::endl;
- glDeleteTextures( 1, &mPickTextureHandle );
- mPickTextureHandle = 0;
- }
-
- if ( isTexture( mMediaTextureHandle ) )
- {
- std::cerr << "remMediaPanel: deleting media texture " << mMediaTextureHandle << std::endl;
- glDeleteTextures( 1, &mMediaTextureHandle );
- mMediaTextureHandle = 0;
- }
-
- if(mPickTexturePixels)
- {
- delete mPickTexturePixels;
- }
-
- if(mMediaSource)
- {
- delete mMediaSource;
- }
-
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-LLMediaPluginTest::LLMediaPluginTest( int app_window, int window_width, int window_height ) :
- mVersionMajor( 2 ),
- mVersionMinor( 0 ),
- mVersionPatch( 0 ),
- mMaxPanels( 25 ),
- mViewportAspect( 0 ),
- mAppWindow( app_window ),
- mCurMouseX( 0 ),
- mCurMouseY( 0 ),
- mFuzzyMedia( true ),
- mSelectedPanel( 0 ),
- mDistanceCameraToSelectedGeometry( 0.0f ),
- mMediaBrowserControlEnableCookies( 0 ),
- mMediaBrowserControlBackButton( 0 ),
- mMediaBrowserControlForwardButton( 0 ),
- mMediaTimeControlVolume( 100 ),
- mMediaTimeControlSeekSeconds( 0 ),
- mGluiMediaTimeControlWindowFlag( true ),
- mGluiMediaBrowserControlWindowFlag( true ),
- mMediaBrowserControlBackButtonFlag( true ),
- mMediaBrowserControlForwardButtonFlag( true ),
- mHomeWebUrl( "http://www.google.com/" )
-{
- // debugging spam
- std::cout << std::endl << " GLUT version: " << "3.7.6" << std::endl; // no way to get real version from GLUT
- std::cout << std::endl << " GLUI version: " << GLUI_Master.get_version() << std::endl;
- std::cout << std::endl << "Media Plugin Test version: " << mVersionMajor << "." << mVersionMinor << "." << mVersionPatch << std::endl;
-
- // bookmark title
- mBookmarks.push_back( std::pair< std::string, std::string >( "--- Bookmarks ---", "" ) );
-
- // insert hardcoded URLs here as required for testing
- //mBookmarks.push_back( std::pair< std::string, std::string >( "description", "url" ) );
-
- // read bookmarks from file.
- // note: uses command in ./CmakeLists.txt which copies bookmmarks file from source directory
- // to app directory (WITHOUT build configuration dir) (this is cwd in Windows within MSVC)
- // For example, test_apps\llplugintest and not test_apps\llplugintest\Release
- // This may need to be changed for Mac/Linux builds.
- // See https://jira.lindenlab.com/browse/DEV-31350 for large list of media URLs from AGNI
- const std::string bookmarks_filename( "bookmarks.txt" );
- std::ifstream file_handle( bookmarks_filename.c_str() );
- if ( file_handle.is_open() )
- {
- std::cout << "Reading bookmarks for test" << std::endl;
- while( ! file_handle.eof() )
- {
- std::string line;
- std::getline( file_handle, line );
- if ( file_handle.eof() )
- break;
-
- if ( line.substr( 0, 1 ) != "#" )
- {
- size_t comma_pos = line.find_first_of( ',' );
- if ( comma_pos != std::string::npos )
- {
- std::string description = line.substr( 0, comma_pos );
- std::string url = line.substr( comma_pos + 1 );
- mBookmarks.push_back( std::pair< std::string, std::string >( description, url ) );
- }
- else
- {
- mBookmarks.push_back( std::pair< std::string, std::string >( line, line ) );
- };
- };
- };
- std::cout << "Read " << mBookmarks.size() << " bookmarks" << std::endl;
- }
- else
- {
- std::cout << "Unable to read bookmarks from file: " << bookmarks_filename << std::endl;
- };
-
- // initialize linden lab APR module
- ll_init_apr();
-
- // Set up llerror logging
- {
- LLError::initForApplication(".");
- LLError::setDefaultLevel(LLError::LEVEL_INFO);
- //LLError::setTagLevel("Plugin", LLError::LEVEL_DEBUG);
- }
-
- // lots of randomness in this app
- srand( ( unsigned int )time( 0 ) );
-
- // build GUI
- makeChrome();
-
- // OpenGL initialilzation
- glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
- glClearDepth( 1.0f );
- glEnable( GL_DEPTH_TEST );
- glEnable( GL_COLOR_MATERIAL );
- glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
- glDepthFunc( GL_LEQUAL );
- glEnable( GL_TEXTURE_2D );
- glDisable( GL_BLEND );
- glColor3f( 1.0f, 1.0f, 1.0f );
- glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
- glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
-
- // start with a sane view
- resetView();
-
- // initial media panel
- const int num_initial_panels = 1;
- for( int i = 0; i < num_initial_panels; ++i )
- {
- //addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second );
- addMediaPanel( mHomeWebUrl );
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-LLMediaPluginTest::~LLMediaPluginTest()
-{
- // delete all media panels
- for( int i = 0; i < (int)mMediaPanels.size(); ++i )
- {
- remMediaPanel( mMediaPanels[ i ] );
- };
-
- // Stop the plugin read thread if it's running.
- LLPluginProcessParent::setUseReadThread(false);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::reshape( int width, int height )
-{
- // update viewport (the active window inside the chrome)
- int viewport_x, viewport_y;
- int viewport_height, viewport_width;
- GLUI_Master.get_viewport_area( &viewport_x, &viewport_y, &viewport_width, &viewport_height );
- mViewportAspect = (float)( viewport_width ) / (float)( viewport_height );
- glViewport( viewport_x, viewport_y, viewport_width, viewport_height );
-
- // save these as we'll need them later
- mWindowWidth = width;
- mWindowHeight = height;
-
- // adjust size of URL bar so it doesn't get clipped
- mUrlEdit->set_w( mWindowWidth - 360 );
-
- // GLUI requires this
- if ( glutGetWindow() != mAppWindow )
- glutSetWindow( mAppWindow );
-
- // trigger re-display
- glutPostRedisplay();
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::bindTexture(GLuint texture, GLint row_length, GLint alignment)
-{
- glEnable( GL_TEXTURE_2D );
-
- glBindTexture( GL_TEXTURE_2D, texture );
- glPixelStorei( GL_UNPACK_ROW_LENGTH, row_length );
- glPixelStorei( GL_UNPACK_ALIGNMENT, alignment );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-bool LLMediaPluginTest::checkGLError(const char *name)
-{
- bool result = false;
- GLenum error = glGetError();
-
- if(error != GL_NO_ERROR)
- {
- // For some reason, glGenTextures is returning GL_INVALID_VALUE...
- std::cout << name << " ERROR 0x" << std::hex << error << std::dec << std::endl;
- result = true;
- }
-
- return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-GLfloat LLMediaPluginTest::distanceToCamera( GLfloat point_x, GLfloat point_y, GLfloat point_z )
-{
- GLdouble camera_pos_x = 0.0f;
- GLdouble camera_pos_y = 0.0f;
- GLdouble camera_pos_z = 0.0f;
-
- GLdouble modelMatrix[16];
- GLdouble projMatrix[16];
- GLint viewport[4];
-
- glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
- glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
- glGetIntegerv(GL_VIEWPORT, viewport);
-
- gluUnProject(
- (viewport[2]-viewport[0])/2 , (viewport[3]-viewport[1])/2,
- 0.0,
- modelMatrix, projMatrix, viewport,
- &camera_pos_x, &camera_pos_y, &camera_pos_z );
-
- GLfloat distance =
- sqrt( ( camera_pos_x - point_x ) * ( camera_pos_x - point_x ) +
- ( camera_pos_y - point_y ) * ( camera_pos_y - point_y ) +
- ( camera_pos_z - point_z ) * ( camera_pos_z - point_z ) );
-
- return distance;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::drawGeometry( int panel, bool selected )
-{
- // texture coordinates for each panel
- GLfloat non_opengl_texture_coords[ 8 ] = { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f };
- GLfloat opengl_texture_coords[ 8 ] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f };
-
- GLfloat *texture_coords = mMediaPanels[ panel ]->mAppTextureCoordsOpenGL?opengl_texture_coords:non_opengl_texture_coords;
-
- // base coordinates for each panel
- GLfloat base_vertex_pos[ 8 ] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f };
-
- // calculate posiitons
- const int num_panels = (int)mMediaPanels.size();
- const int num_rows = (int)sqrt( (float)num_panels );
- const int num_cols = num_panels / num_rows;
- const int panel_x = ( panel / num_rows );
- const int panel_y = ( panel % num_rows );
-
- // default spacing is small - make it larger if checkbox set - for testing positional audio
- float spacing = 0.1f;
- if ( mLargePanelSpacing )
- spacing = 2.0f;
-
- const GLfloat offset_x = num_cols * ( 1.0 + spacing ) / 2;
- const GLfloat offset_y = num_rows * ( 1.0 + spacing ) / 2;
-
- // Adjust for media aspect ratios
- {
- float aspect = 1.0f;
-
- if(mMediaPanels[ panel ]->mMediaHeight != 0)
- {
- aspect = (float)mMediaPanels[ panel ]->mMediaWidth / (float)mMediaPanels[ panel ]->mMediaHeight;
- }
-
- if(aspect > 1.0f)
- {
- // media is wider than it is high -- adjust the top and bottom in
- for( int corner = 0; corner < 4; ++corner )
- {
- float temp = base_vertex_pos[corner * 2 + 1];
-
- if(temp < 0.5f)
- temp += 0.5 - (0.5f / aspect);
- else
- temp -= 0.5 - (0.5f / aspect);
-
- base_vertex_pos[corner * 2 + 1] = temp;
- }
- }
- else if(aspect < 1.0f)
- {
- // media is higher than it is wide -- adjust the left and right sides in
- for( int corner = 0; corner < 4; ++corner )
- {
- float temp = base_vertex_pos[corner * 2];
-
- if(temp < 0.5f)
- temp += 0.5f - (0.5f * aspect);
- else
- temp -= 0.5f - (0.5f * aspect);
-
- base_vertex_pos[corner * 2] = temp;
- }
- }
- }
-
- glBegin( GL_QUADS );
- for( int corner = 0; corner < 4; ++corner )
- {
- glTexCoord2f( texture_coords[ corner * 2 ], texture_coords[ corner * 2 + 1 ] );
- GLfloat x = base_vertex_pos[ corner * 2 ] + panel_x * ( 1.0 + spacing ) - offset_x + spacing / 2.0f;
- GLfloat y = base_vertex_pos[ corner * 2 + 1 ] + panel_y * ( 1.0 + spacing ) - offset_y + spacing / 2.0f;
-
- glVertex3f( x, y, 0.0f );
- };
- glEnd();
-
- // calculate distance to this panel if it's selected
- if ( selected )
- {
- GLfloat point_x = base_vertex_pos[ 0 ] + panel_x * ( 1.0 + spacing ) - offset_x + spacing / 2.0f;
- GLfloat point_y = base_vertex_pos[ 0 + 1 ] + panel_y * ( 1.0 + spacing ) - offset_y + spacing / 2.0f;
- GLfloat point_z = 0.0f;
- mDistanceCameraToSelectedGeometry = distanceToCamera( point_x, point_y, point_z );
- };
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::startPanelHighlight( float red, float green, float blue, float line_width )
-{
- glPushAttrib( GL_ALL_ATTRIB_BITS );
- glEnable( GL_POLYGON_OFFSET_FILL );
- glPolygonOffset( -2.5f, -2.5f );
- glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
- glLineWidth( line_width );
- glColor3f( red, green, blue );
- glDisable( GL_TEXTURE_2D );
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::endPanelHighlight()
-{
- glPopAttrib();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::draw( int draw_type )
-{
- for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
- {
- // drawing pick texture
- if ( draw_type == DrawTypePickTexture )
- {
- // only bother with pick if we have something to render
- // Actually, we need to pick even if we're not ready to render.
- // Otherwise you can't select and remove a panel which has gone bad.
- //if ( mMediaPanels[ panel ]->mReadyToRender )
- {
- glMatrixMode( GL_TEXTURE );
- glPushMatrix();
-
- // pick texture is a power of 2 so no need to scale
- glLoadIdentity();
-
- // bind to media texture
- glLoadIdentity();
- bindTexture( mMediaPanels[ panel ]->mPickTextureHandle );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
-
- // draw geometry using pick texture
- drawGeometry( panel, false );
-
- glMatrixMode( GL_TEXTURE );
- glPopMatrix();
- };
- }
- else
- if ( draw_type == DrawTypeMediaTexture )
- {
- bool texture_valid = false;
- bool plugin_exited = false;
-
- if(mMediaPanels[ panel ]->mMediaSource)
- {
- texture_valid = mMediaPanels[ panel ]->mMediaSource->textureValid();
- plugin_exited = mMediaPanels[ panel ]->mMediaSource->isPluginExited();
- }
-
- // save texture matrix (changes for each panel)
- glMatrixMode( GL_TEXTURE );
- glPushMatrix();
-
- // only process texture if the media is ready to draw
- // (we still want to draw the geometry)
- if ( mMediaPanels[ panel ]->mReadyToRender && texture_valid )
- {
- // bind to media texture
- bindTexture( mMediaPanels[ panel ]->mMediaTextureHandle );
-
- if ( mFuzzyMedia )
- {
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- }
- else
- {
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
- }
-
- // scale to fit panel
- glScalef( mMediaPanels[ panel ]->mTextureScaleX,
- mMediaPanels[ panel ]->mTextureScaleY,
- 1.0f );
- };
-
- float intensity = plugin_exited?0.25f:1.0f;
-
- // highlight the selected panel
- if ( mSelectedPanel && ( mMediaPanels[ panel ]->mId == mSelectedPanel->mId ) )
- {
- startPanelHighlight( intensity, intensity, 0.0f, 5.0f );
- drawGeometry( panel, true );
- endPanelHighlight();
- }
- else
- // this panel not able to render yet since it
- // doesn't have enough information
- if ( !mMediaPanels[ panel ]->mReadyToRender )
- {
- startPanelHighlight( intensity, 0.0f, 0.0f, 2.0f );
- drawGeometry( panel, false );
- endPanelHighlight();
- }
- else
- // just display a border around the media
- {
- startPanelHighlight( 0.0f, intensity, 0.0f, 2.0f );
- drawGeometry( panel, false );
- endPanelHighlight();
- };
-
- if ( mMediaPanels[ panel ]->mReadyToRender && texture_valid )
- {
- // draw visual geometry
- drawGeometry( panel, false );
- }
-
- // restore texture matrix (changes for each panel)
- glMatrixMode( GL_TEXTURE );
- glPopMatrix();
- };
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::display()
-{
- // GLUI requires this
- if ( glutGetWindow() != mAppWindow )
- glutSetWindow( mAppWindow );
-
- // start with a clean slate
- glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-
- // set up OpenGL view
- glMatrixMode( GL_PROJECTION );
- glLoadIdentity();
- glFrustum( -mViewportAspect * 0.04f, mViewportAspect * 0.04f, -0.04f, 0.04f, 0.1f, 50.0f );
- glMatrixMode( GL_MODELVIEW );
- glLoadIdentity();
- glTranslatef( 0.0, 0.0, 0.0f );
- glTranslatef( mViewPos[ 0 ], mViewPos[ 1 ], -mViewPos[ 2 ] );
- glMultMatrixf( mViewRotation );
-
- // draw pick texture
- draw( DrawTypePickTexture );
-
- // read colors and get coordinate values
- glReadPixels( mCurMouseX, mCurMouseY, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, mPixelReadColor );
-
- // clear the pick render (otherwise it may depth-fight with the textures rendered later)
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-
- // draw visible geometry
- draw( DrawTypeMediaTexture );
-
- glutSwapBuffers();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::idle()
-{
-// checkGLError("LLMediaPluginTest::idle");
-
- // GLUI requires this
- if ( glutGetWindow() != mAppWindow )
- glutSetWindow( mAppWindow );
-
- // random creation/destruction of panels enabled?
- const time_t panel_timeout_time = 5;
- if ( mRandomPanelCount )
- {
- // time for a change
- static time_t last_panel_time = 0;
- if ( time( NULL ) - last_panel_time > panel_timeout_time )
- {
- if ( rand() % 2 == 0 )
- {
- if ( mMediaPanels.size() < 16 )
- {
- std::cout << "Randomly adding new panel" << std::endl;
- addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second );
- };
- }
- else
- {
- if ( mMediaPanels.size() > 0 )
- {
- std::cout << "Deleting selected panel" << std::endl;
- remMediaPanel( mSelectedPanel );
- };
- };
- time( &last_panel_time );
- };
- };
-
- // random selection of bookmarks enabled?
- const time_t bookmark_timeout_time = 5;
- if ( mRandomBookmarks )
- {
- // time for a change
- static time_t last_bookmark_time = 0;
- if ( time( NULL ) - last_bookmark_time > bookmark_timeout_time )
- {
- // go to a different random bookmark on each panel
- for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
- {
- std::string uri = mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second;
-
- std::cout << "Random: navigating to : " << uri << std::endl;
-
- std::string mime_type = mimeTypeFromUrl( uri );
-
- if ( mime_type != mMediaPanels[ panel ]->mMimeType )
- {
- replaceMediaPanel( mMediaPanels[ panel ], uri );
- }
- else
- {
- mMediaPanels[ panel ]->mMediaSource->loadURI( uri );
- mMediaPanels[ panel ]->mMediaSource->start();
- };
- };
-
- time( &last_bookmark_time );
- };
- };
-
- // update UI
- if ( mSelectedPanel )
- {
- // set volume based on slider if we have time media
- //if ( mGluiMediaTimeControlWindowFlag )
- //{
- // mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f );
- //};
-
- // NOTE: it is absurd that we need cache the state of GLUI controls
- // but enabling/disabling controls drags framerate from 500+
- // down to 15. Not a problem for plugin system - only this test
- // enable/disable time based UI controls based on type of plugin
- if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() )
- {
- if ( ! mGluiMediaTimeControlWindowFlag )
- {
- mGluiMediaTimeControlWindow->enable();
- mGluiMediaTimeControlWindowFlag = true;
- };
- }
- else
- {
- if ( mGluiMediaTimeControlWindowFlag )
- {
- mGluiMediaTimeControlWindow->disable();
- mGluiMediaTimeControlWindowFlag = false;
- };
- };
-
- // enable/disable browser based UI controls based on type of plugin
- if ( mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() )
- {
- if ( ! mGluiMediaBrowserControlWindowFlag )
- {
- mGluiMediaBrowserControlWindow->enable();
- mGluiMediaBrowserControlWindowFlag = true;
- };
- }
- else
- {
- if ( mGluiMediaBrowserControlWindowFlag )
- {
- mGluiMediaBrowserControlWindow->disable();
- mGluiMediaBrowserControlWindowFlag = false;
- };
- };
-
- // enable/disable browser back button depending on browser history
- if ( mSelectedPanel->mMediaSource->getHistoryBackAvailable() )
- {
- if ( ! mMediaBrowserControlBackButtonFlag )
- {
- mMediaBrowserControlBackButton->enable();
- mMediaBrowserControlBackButtonFlag = true;
- };
- }
- else
- {
- if ( mMediaBrowserControlBackButtonFlag )
- {
- mMediaBrowserControlBackButton->disable();
- mMediaBrowserControlBackButtonFlag = false;
- };
- };
-
- // enable/disable browser forward button depending on browser history
- if ( mSelectedPanel->mMediaSource->getHistoryForwardAvailable() )
- {
- if ( ! mMediaBrowserControlForwardButtonFlag )
- {
- mMediaBrowserControlForwardButton->enable();
- mMediaBrowserControlForwardButtonFlag = true;
- };
- }
- else
- {
- if ( mMediaBrowserControlForwardButtonFlag )
- {
- mMediaBrowserControlForwardButton->disable();
- mMediaBrowserControlForwardButtonFlag = false;
- };
- };
-
- // NOTE: This is *very* slow and not worth optimising
- updateStatusBar();
- };
-
- // update all the panels
- for( int panel_index = 0; panel_index < (int)mMediaPanels.size(); ++panel_index )
- {
- mediaPanel *panel = mMediaPanels[ panel_index ];
-
- // call plugins idle function so it can potentially update itself
- panel->mMediaSource->idle();
-
- // update each media panel
- updateMediaPanel( panel );
-
- LLRect dirty_rect;
- if ( ! panel->mMediaSource->textureValid() )
- {
- //std::cout << "texture invalid, skipping update..." << std::endl;
- }
- else
- if ( panel &&
- ( panel->mMediaWidth != panel->mMediaSource->getWidth() ||
- panel->mMediaHeight != panel->mMediaSource->getHeight() ) )
- {
- //std::cout << "Resize in progress, skipping update..." << std::endl;
- }
- else
- if ( panel->mMediaSource->getDirty( &dirty_rect ) )
- {
- const unsigned char* pixels = panel->mMediaSource->getBitsData();
- if ( pixels && isTexture(panel->mMediaTextureHandle))
- {
- int x_offset = dirty_rect.mLeft;
- int y_offset = dirty_rect.mBottom;
- int width = dirty_rect.mRight - dirty_rect.mLeft;
- int height = dirty_rect.mTop - dirty_rect.mBottom;
-
- if((dirty_rect.mRight <= panel->mTextureWidth) && (dirty_rect.mTop <= panel->mTextureHeight))
- {
- // Offset the pixels pointer properly
- pixels += ( y_offset * panel->mMediaSource->getTextureDepth() * panel->mMediaSource->getBitsWidth() );
- pixels += ( x_offset * panel->mMediaSource->getTextureDepth() );
-
- // set up texture
- bindTexture( panel->mMediaTextureHandle, panel->mMediaSource->getBitsWidth() );
- if ( mFuzzyMedia )
- {
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- }
- else
- {
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
- };
-
- checkGLError("glTexParameteri");
-
- if(panel->mMediaSource->getTextureFormatSwapBytes())
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
- checkGLError("glPixelStorei");
- }
-
- // draw portion that changes into texture
- glTexSubImage2D( GL_TEXTURE_2D, 0,
- x_offset,
- y_offset,
- width,
- height,
- panel->mMediaSource->getTextureFormatPrimary(),
- panel->mMediaSource->getTextureFormatType(),
- pixels );
-
- if(checkGLError("glTexSubImage2D"))
- {
- std::cerr << " panel ID=" << panel->mId << std::endl;
- std::cerr << " texture size = " << panel->mTextureWidth << " x " << panel->mTextureHeight << std::endl;
- std::cerr << " media size = " << panel->mMediaWidth << " x " << panel->mMediaHeight << std::endl;
- std::cerr << " dirty rect = " << dirty_rect.mLeft << ", " << dirty_rect.mBottom << ", " << dirty_rect.mRight << ", " << dirty_rect.mTop << std::endl;
- std::cerr << " texture width = " << panel->mMediaSource->getBitsWidth() << std::endl;
- std::cerr << " format primary = 0x" << std::hex << panel->mMediaSource->getTextureFormatPrimary() << std::dec << std::endl;
- std::cerr << " format type = 0x" << std::hex << panel->mMediaSource->getTextureFormatType() << std::dec << std::endl;
- std::cerr << " pixels = " << (void*)pixels << std::endl;
- }
-
- if(panel->mMediaSource->getTextureFormatSwapBytes())
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
- checkGLError("glPixelStorei");
- }
-
- panel->mMediaSource->resetDirty();
-
- panel->mReadyToRender = true;
- }
- else
- {
- std::cerr << "dirty rect is outside current media size, skipping update" << std::endl;
- }
- };
- };
- };
-
- // GLUI requires this
- if ( glutGetWindow() != mAppWindow )
- glutSetWindow( mAppWindow );
-
- // trigger re-display
- glutPostRedisplay();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::windowPosToTexturePos( int window_x, int window_y,
- int& media_x, int& media_y,
- int& id )
-{
- if ( ! mSelectedPanel )
- {
- media_x = 0;
- media_y = 0;
- id = 0;
- return;
- };
-
- // record cursor poisiton for a readback next frame
- mCurMouseX = window_x;
- // OpenGL app == coordinate system this way
- // NOTE: unrelated to settings in plugin - this
- // is just for this app
- mCurMouseY = mWindowHeight - window_y;
-
- // extract x (0..1023, y (0..1023) and id (0..15) from RGB components
- unsigned long pixel_read_color_bits = ( mPixelReadColor[ 0 ] << 16 ) | ( mPixelReadColor[ 1 ] << 8 ) | mPixelReadColor[ 2 ];
- int texture_x = pixel_read_color_bits & 0x3ff;
- int texture_y = ( pixel_read_color_bits >> 10 ) & 0x3ff;
- id = ( pixel_read_color_bits >> 20 ) & 0x0f;
-
- // scale to size of media (1024 because we use 10 bits for X and Y from 24)
- media_x = (int)( ( (float)mSelectedPanel->mMediaWidth * (float)texture_x ) / 1024.0f );
- media_y = (int)( ( (float)mSelectedPanel->mMediaHeight * (float)texture_y ) / 1024.0f );
-
- // we assume the plugin uses an inverted coordinate scheme like OpenGL
- // if not, the plugin code inverts the Y coordinate for us - we don't need to
- media_y = mSelectedPanel->mMediaHeight - media_y;
-
- if ( media_x > 0 && media_y > 0 )
- {
- //std::cout << " mouse coords: " << mCurMouseX << " x " << mCurMouseY << " and id = " << id << std::endl;
- //std::cout << "raw texture coords: " << texture_x << " x " << texture_y << " and id = " << id << std::endl;
- //std::cout << " media coords: " << media_x << " x " << media_y << " and id = " << id << std::endl;
- //std::cout << std::endl;
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::selectPanelById( int id )
-{
- for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
- {
- if ( mMediaPanels[ panel ]->mId == id )
- {
- selectPanel(mMediaPanels[ panel ]);
- return;
- };
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::selectPanel( mediaPanel* panel )
-{
- if( mSelectedPanel == panel )
- return;
-
- // turn off volume before we delete it
- if( mSelectedPanel && mSelectedPanel->mMediaSource )
- {
- mSelectedPanel->mMediaSource->setVolume( 0.0f );
- mSelectedPanel->mMediaSource->setPriority( LLPluginClassMedia::PRIORITY_LOW );
- };
-
- mSelectedPanel = panel;
-
- if( mSelectedPanel && mSelectedPanel->mMediaSource )
- {
- mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f );
- mSelectedPanel->mMediaSource->setPriority( LLPluginClassMedia::PRIORITY_NORMAL );
-
- if(!mSelectedPanel->mStartUrl.empty())
- {
- mUrlEdit->set_text(const_cast<char*>(mSelectedPanel->mStartUrl.c_str()) );
- }
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-mediaPanel* LLMediaPluginTest::findMediaPanel( LLPluginClassMedia* source )
-{
- mediaPanel *result = NULL;
-
- for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
- {
- if ( mMediaPanels[ panel ]->mMediaSource == source )
- {
- result = mMediaPanels[ panel ];
- }
- }
-
- return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-mediaPanel* LLMediaPluginTest::findMediaPanel( const std::string &target_name )
-{
- mediaPanel *result = NULL;
-
- for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
- {
- if ( mMediaPanels[ panel ]->mTarget == target_name )
- {
- result = mMediaPanels[ panel ];
- }
- }
-
- return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::navigateToNewURI( std::string uri )
-{
- if ( uri.length() )
- {
- std::string mime_type = mimeTypeFromUrl( uri );
-
- if ( !mSelectedPanel->mMediaSource->isPluginExited() && (mime_type == mSelectedPanel->mMimeType) )
- {
- std::cout << "MIME type is the same" << std::endl;
- mSelectedPanel->mMediaSource->loadURI( uri );
- mSelectedPanel->mMediaSource->start();
- mBookmarkList->do_selection( 0 );
- }
- else
- {
- std::cout << "MIME type changed or plugin had exited" << std::endl;
- replaceMediaPanel( mSelectedPanel, uri );
- mBookmarkList->do_selection( 0 );
- }
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::initUrlHistory( std::string uris )
-{
- if ( uris.length() > 0 )
- {
- std::cout << "init URL : " << uris << std::endl;
- LLSD historySD;
-
- char *cstr, *p;
- cstr = new char[uris.size()+1];
- strcpy(cstr, uris.c_str());
- const char *DELIMS = " ,;";
- p = strtok(cstr, DELIMS);
- while (p != NULL) {
- historySD.insert(0, p);
- p = strtok(NULL, DELIMS);
- }
- mSelectedPanel->mMediaSource->initializeUrlHistory(historySD);
- delete[] cstr;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::gluiCallback( int control_id )
-{
- if ( control_id == mIdBookmarks )
- {
- std::string uri = mBookmarks[ mSelBookmark ].second;
-
- navigateToNewURI( uri );
- }
- else
- if ( control_id == mIdUrlEdit)
- {
- std::string uri = mUrlEdit->get_text();
-
- navigateToNewURI( uri );
- }
- else
- if ( control_id == mIdUrlInitHistoryEdit )
- {
- std::string uri = mUrlInitHistoryEdit->get_text();
-
- initUrlHistory( uri );
- }
- else
- if ( control_id == mIdControlAddPanel )
- {
- addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second );
- }
- else
- if ( control_id == mIdControlRemPanel )
- {
- remMediaPanel( mSelectedPanel );
- }
- else
- if ( control_id == mIdDisableTimeout )
- {
- // Set the "disable timeout" flag for all active plugins.
- for( int i = 0; i < (int)mMediaPanels.size(); ++i )
- {
- mMediaPanels[ i ]->mMediaSource->setDisableTimeout(mDisableTimeout);
- }
- }
- else
- if ( control_id == mIdUsePluginReadThread )
- {
- LLPluginProcessParent::setUseReadThread(mUsePluginReadThread);
- }
- else
- if ( control_id == mIdControlCrashPlugin )
- {
- // send message to plugin and ask it to crash
- // (switch out for ReleaseCandidate version :) )
- if(mSelectedPanel && mSelectedPanel->mMediaSource)
- {
- mSelectedPanel->mMediaSource->crashPlugin();
- }
- }
- else
- if ( control_id == mIdControlHangPlugin )
- {
- // send message to plugin and ask it to hang
- // (switch out for ReleaseCandidate version :) )
- if(mSelectedPanel && mSelectedPanel->mMediaSource)
- {
- mSelectedPanel->mMediaSource->hangPlugin();
- }
- }
- else
- if ( control_id == mIdControlExitApp )
- {
- // text for exiting plugin system cleanly
- delete this; // clean up
- exit( 0 );
- }
- else
- if ( control_id == mIdMediaTimeControlPlay )
- {
- if ( mSelectedPanel )
- {
- mSelectedPanel->mMediaSource->setLoop( false );
- mSelectedPanel->mMediaSource->start();
- };
- }
- else
- if ( control_id == mIdMediaTimeControlLoop )
- {
- if ( mSelectedPanel )
- {
- mSelectedPanel->mMediaSource->setLoop( true );
- mSelectedPanel->mMediaSource->start();
- };
- }
- else
- if ( control_id == mIdMediaTimeControlPause )
- {
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->pause();
- }
- else
- if ( control_id == mIdMediaTimeControlStop )
- {
- if ( mSelectedPanel )
- {
- mSelectedPanel->mMediaSource->stop();
- };
- }
- else
- if ( control_id == mIdMediaTimeControlSeek )
- {
- if ( mSelectedPanel )
- {
- // get value from spinner
- float seconds_to_seek = mMediaTimeControlSeekSeconds;
- mSelectedPanel->mMediaSource->seek( seconds_to_seek );
- mSelectedPanel->mMediaSource->start();
- };
- }
- else
- if ( control_id == mIdMediaTimeControlRewind )
- {
- if ( mSelectedPanel )
- {
- mSelectedPanel->mMediaSource->setLoop( false );
- mSelectedPanel->mMediaSource->start(-2.0f);
- };
- }
- else
- if ( control_id == mIdMediaTimeControlFastForward )
- {
- if ( mSelectedPanel )
- {
- mSelectedPanel->mMediaSource->setLoop( false );
- mSelectedPanel->mMediaSource->start(2.0f);
- };
- }
- else
- if ( control_id == mIdMediaBrowserControlBack )
- {
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->browse_back();
- }
- else
- if ( control_id == mIdMediaBrowserControlStop )
- {
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->browse_stop();
- }
- else
- if ( control_id == mIdMediaBrowserControlForward )
- {
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->browse_forward();
- }
- else
- if ( control_id == mIdMediaBrowserControlHome )
- {
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->loadURI( mHomeWebUrl );
- }
- else
- if ( control_id == mIdMediaBrowserControlReload )
- {
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->browse_reload( true );
- }
- else
- if ( control_id == mIdMediaBrowserControlClearCache )
- {
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->clear_cache();
- }
- else
- if ( control_id == mIdMediaBrowserControlClearCookies )
- {
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->clear_cookies();
- }
- else
- if ( control_id == mIdMediaBrowserControlEnableCookies )
- {
- if ( mSelectedPanel )
- {
- if ( mMediaBrowserControlEnableCookies )
- {
- mSelectedPanel->mMediaSource->enable_cookies( true );
- }
- else
- {
- mSelectedPanel->mMediaSource->enable_cookies( false );
- }
- };
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::keyboard( int key )
-{
- //if ( key == 'a' || key == 'A' )
- // addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second );
- //else
- //if ( key == 'r' || key == 'R' )
- // remMediaPanel( mSelectedPanel );
- //else
- //if ( key == 'd' || key == 'D' )
- // dumpPanelInfo();
- //else
- if ( key == 27 )
- {
- std::cout << "Application finished - exiting..." << std::endl;
- delete this;
- exit( 0 );
- };
-
- mSelectedPanel->mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_DOWN, key, 0 , LLSD());
- mSelectedPanel->mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_UP, key, 0, LLSD());
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::mouseButton( int button, int state, int x, int y )
-{
- if ( button == GLUT_LEFT_BUTTON )
- {
- if ( state == GLUT_DOWN )
- {
- int media_x, media_y, id;
- windowPosToTexturePos( x, y, media_x, media_y, id );
-
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_DOWN, 0, media_x, media_y, 0 );
- }
- else
- if ( state == GLUT_UP )
- {
- int media_x, media_y, id;
- windowPosToTexturePos( x, y, media_x, media_y, id );
-
- // only select a panel if we're on a panel
- // (HACK: strictly speaking this rules out clicking on
- // the origin of a panel but that's very unlikely)
- if ( media_x > 0 && media_y > 0 )
- {
- selectPanelById( id );
-
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_UP, 0, media_x, media_y, 0 );
- };
- };
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::mousePassive( int x, int y )
-{
- int media_x, media_y, id;
- windowPosToTexturePos( x, y, media_x, media_y, id );
-
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, media_x, media_y, 0 );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::mouseMove( int x, int y )
-{
- int media_x, media_y, id;
- windowPosToTexturePos( x, y, media_x, media_y, id );
-
- if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, media_x, media_y, 0 );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::makeChrome()
-{
- // IDs used by GLUI
- int start_id = 0x1000;
-
- // right side window - geometry manipulators
-#if __APPLE__
- // the Apple GLUT implementation doesn't seem to set the graphic offset of subwindows correctly when they overlap in certain ways.
- // Use a separate controls window in this case.
- // GLUI window at right containing manipulation controls and other buttons
- int x = glutGet(GLUT_WINDOW_X) + glutGet(GLUT_WINDOW_WIDTH) + 4;
- int y = glutGet(GLUT_WINDOW_Y);
- GLUI* right_glui_window = GLUI_Master.create_glui( "", 0, x, y );
-#else
- GLUI* right_glui_window = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_RIGHT );
-#endif
- mViewRotationCtrl = right_glui_window->add_rotation( "Rotation", mViewRotation );
- mViewTranslationCtrl = right_glui_window->add_translation( "Translate", GLUI_TRANSLATION_XY, mViewPos );
- mViewTranslationCtrl->set_speed( 0.01f );
- mViewScaleCtrl = right_glui_window->add_translation( "Scale", GLUI_TRANSLATION_Z, &mViewPos[ 2 ] );
- mViewScaleCtrl->set_speed( 0.05f );
- right_glui_window->set_main_gfx_window( mAppWindow );
-
- // right side window - app controls
- mIdControlAddPanel = start_id++;
- right_glui_window->add_statictext( "" );
- right_glui_window->add_separator();
- right_glui_window->add_statictext( "" );
- right_glui_window->add_button( "Add panel", mIdControlAddPanel, gluiCallbackWrapper );
- right_glui_window->add_statictext( "" );
- mIdControlRemPanel = start_id++;
- right_glui_window->add_button( "Rem panel", mIdControlRemPanel, gluiCallbackWrapper );
- right_glui_window->add_statictext( "" );
- right_glui_window->add_separator();
- right_glui_window->add_statictext( "" );
- mIdControlCrashPlugin = start_id++;
- right_glui_window->add_button( "Crash plugin", mIdControlCrashPlugin, gluiCallbackWrapper );
- mIdControlHangPlugin = start_id++;
- right_glui_window->add_button( "Hang plugin", mIdControlHangPlugin, gluiCallbackWrapper );
-
- right_glui_window->add_statictext( "" );
- right_glui_window->add_separator();
- right_glui_window->add_statictext( "" );
- mIdControlExitApp = start_id++;
- right_glui_window->add_button( "Exit app", mIdControlExitApp, gluiCallbackWrapper );
-
- //// top window - holds bookmark UI
- mIdBookmarks = start_id++;
- mSelBookmark = 0;
- GLUI* glui_window_top = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
- mBookmarkList = glui_window_top->add_listbox( "", &mSelBookmark, mIdBookmarks, gluiCallbackWrapper );
- // only add the first 50 bookmarks - list can be very long sometimes (30,000+)
- // when testing list of media URLs from AGNI for example
- for( unsigned int each = 0; each < mBookmarks.size() && each < 50; ++each )
- mBookmarkList->add_item( each, const_cast< char* >( mBookmarks[ each ].first.c_str() ) );
- glui_window_top->set_main_gfx_window( mAppWindow );
-
- glui_window_top->add_column( false );
- mIdUrlEdit = start_id++;
- mUrlEdit = glui_window_top->add_edittext( "Url:", GLUI_EDITTEXT_TEXT, 0, mIdUrlEdit, gluiCallbackWrapper );
- mUrlEdit->set_w( 600 );
- GLUI* glui_window_top2 = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
- mIdUrlInitHistoryEdit = start_id++;
- mUrlInitHistoryEdit = glui_window_top2->add_edittext( "Init History (separate by commas or semicolons):",
- GLUI_EDITTEXT_TEXT, 0, mIdUrlInitHistoryEdit, gluiCallbackWrapper );
- mUrlInitHistoryEdit->set_w( 800 );
-
- // top window - media controls for "time" media types (e.g. movies)
- mGluiMediaTimeControlWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
- mGluiMediaTimeControlWindow->set_main_gfx_window( mAppWindow );
- mIdMediaTimeControlPlay = start_id++;
- mGluiMediaTimeControlWindow->add_button( "PLAY", mIdMediaTimeControlPlay, gluiCallbackWrapper );
- mGluiMediaTimeControlWindow->add_column( false );
- mIdMediaTimeControlLoop = start_id++;
- mGluiMediaTimeControlWindow->add_button( "LOOP", mIdMediaTimeControlLoop, gluiCallbackWrapper );
- mGluiMediaTimeControlWindow->add_column( false );
- mIdMediaTimeControlPause = start_id++;
- mGluiMediaTimeControlWindow->add_button( "PAUSE", mIdMediaTimeControlPause, gluiCallbackWrapper );
- mGluiMediaTimeControlWindow->add_column( false );
-
- GLUI_Button *button;
- mIdMediaTimeControlRewind = start_id++;
- button = mGluiMediaTimeControlWindow->add_button( "<<", mIdMediaTimeControlRewind, gluiCallbackWrapper );
- button->set_w(30);
- mGluiMediaTimeControlWindow->add_column( false );
- mIdMediaTimeControlFastForward = start_id++;
- button = mGluiMediaTimeControlWindow->add_button( ">>", mIdMediaTimeControlFastForward, gluiCallbackWrapper );
- button->set_w(30);
-
- mGluiMediaTimeControlWindow->add_column( true );
-
- mIdMediaTimeControlStop = start_id++;
- mGluiMediaTimeControlWindow->add_button( "STOP", mIdMediaTimeControlStop, gluiCallbackWrapper );
- mGluiMediaTimeControlWindow->add_column( false );
- mIdMediaTimeControlVolume = start_id++;
- GLUI_Spinner* spinner = mGluiMediaTimeControlWindow->add_spinner( "Volume", 2, &mMediaTimeControlVolume, mIdMediaTimeControlVolume, gluiCallbackWrapper);
- spinner->set_float_limits( 0, 100 );
- mGluiMediaTimeControlWindow->add_column( true );
- mIdMediaTimeControlSeekSeconds = start_id++;
- spinner = mGluiMediaTimeControlWindow->add_spinner( "", 2, &mMediaTimeControlSeekSeconds, mIdMediaTimeControlSeekSeconds, gluiCallbackWrapper);
- spinner->set_float_limits( 0, 200 );
- spinner->set_w( 32 );
- spinner->set_speed( 0.025f );
- mGluiMediaTimeControlWindow->add_column( false );
- mIdMediaTimeControlSeek = start_id++;
- mGluiMediaTimeControlWindow->add_button( "SEEK", mIdMediaTimeControlSeek, gluiCallbackWrapper );
- mGluiMediaTimeControlWindow->add_column( false );
-
-
- // top window - media controls for "browser" media types (e.g. web browser)
- mGluiMediaBrowserControlWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
- mGluiMediaBrowserControlWindow->set_main_gfx_window( mAppWindow );
- mIdMediaBrowserControlBack = start_id++;
- mMediaBrowserControlBackButton = mGluiMediaBrowserControlWindow->add_button( "BACK", mIdMediaBrowserControlBack, gluiCallbackWrapper );
- mGluiMediaBrowserControlWindow->add_column( false );
- mIdMediaBrowserControlStop = start_id++;
- mGluiMediaBrowserControlWindow->add_button( "STOP", mIdMediaBrowserControlStop, gluiCallbackWrapper );
- mGluiMediaBrowserControlWindow->add_column( false );
- mIdMediaBrowserControlForward = start_id++;
- mMediaBrowserControlForwardButton = mGluiMediaBrowserControlWindow->add_button( "FORWARD", mIdMediaBrowserControlForward, gluiCallbackWrapper );
- mGluiMediaBrowserControlWindow->add_column( false );
- mIdMediaBrowserControlHome = start_id++;
- mGluiMediaBrowserControlWindow->add_button( "HOME", mIdMediaBrowserControlHome, gluiCallbackWrapper );
- mGluiMediaBrowserControlWindow->add_column( false );
- mIdMediaBrowserControlReload = start_id++;
- mGluiMediaBrowserControlWindow->add_button( "RELOAD", mIdMediaBrowserControlReload, gluiCallbackWrapper );
- mGluiMediaBrowserControlWindow->add_column( false );
- mIdMediaBrowserControlClearCache = start_id++;
- mGluiMediaBrowserControlWindow->add_button( "CLEAR CACHE", mIdMediaBrowserControlClearCache, gluiCallbackWrapper );
- mGluiMediaBrowserControlWindow->add_column( false );
- mIdMediaBrowserControlClearCookies = start_id++;
- mGluiMediaBrowserControlWindow->add_button( "CLEAR COOKIES", mIdMediaBrowserControlClearCookies, gluiCallbackWrapper );
- mGluiMediaBrowserControlWindow->add_column( false );
- mIdMediaBrowserControlEnableCookies = start_id++;
- mMediaBrowserControlEnableCookies = 0;
- mGluiMediaBrowserControlWindow->add_checkbox( "Enable Cookies", &mMediaBrowserControlEnableCookies, mIdMediaBrowserControlEnableCookies, gluiCallbackWrapper );
-
- // top window - misc controls
- GLUI* glui_window_misc_control = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
- mIdRandomPanelCount = start_id++;
- mRandomPanelCount = 0;
- glui_window_misc_control->add_checkbox( "Randomize panel count", &mRandomPanelCount, mIdRandomPanelCount, gluiCallbackWrapper );
- glui_window_misc_control->set_main_gfx_window( mAppWindow );
- glui_window_misc_control->add_column( true );
- mIdRandomBookmarks = start_id++;
- mRandomBookmarks = 0;
- glui_window_misc_control->add_checkbox( "Randomize bookmarks", &mRandomBookmarks, mIdRandomBookmarks, gluiCallbackWrapper );
- glui_window_misc_control->set_main_gfx_window( mAppWindow );
- glui_window_misc_control->add_column( true );
-
- mIdDisableTimeout = start_id++;
- mDisableTimeout = 0;
- glui_window_misc_control->add_checkbox( "Disable plugin timeout", &mDisableTimeout, mIdDisableTimeout, gluiCallbackWrapper );
- glui_window_misc_control->set_main_gfx_window( mAppWindow );
- glui_window_misc_control->add_column( true );
-
- mIdUsePluginReadThread = start_id++;
- mUsePluginReadThread = 0;
- glui_window_misc_control->add_checkbox( "Use plugin read thread", &mUsePluginReadThread, mIdUsePluginReadThread, gluiCallbackWrapper );
- glui_window_misc_control->set_main_gfx_window( mAppWindow );
- glui_window_misc_control->add_column( true );
-
- mIdLargePanelSpacing = start_id++;
- mLargePanelSpacing = 0;
- glui_window_misc_control->add_checkbox( "Large Panel Spacing", &mLargePanelSpacing, mIdLargePanelSpacing, gluiCallbackWrapper );
- glui_window_misc_control->set_main_gfx_window( mAppWindow );
- glui_window_misc_control->add_column( true );
-
- // bottom window - status
- mBottomGLUIWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_BOTTOM );
- mStatusText = mBottomGLUIWindow->add_statictext( "" );
- mBottomGLUIWindow->set_main_gfx_window( mAppWindow );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::resetView()
-{
- mViewRotationCtrl->reset();
-
- mViewScaleCtrl->set_x( 0.0f );
- mViewScaleCtrl->set_y( 0.0f );
- mViewScaleCtrl->set_z( 3.0f );
-
- mViewTranslationCtrl->set_x( 0.0f );
- mViewTranslationCtrl->set_y( 0.0f );
- mViewTranslationCtrl->set_z( 0.0f );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::makePickTexture( int id, GLuint* texture_handle, unsigned char** texture_pixels )
-{
- int pick_texture_width = 1024;
- int pick_texture_height = 1024;
- int pick_texture_depth = 3;
- unsigned char* ptr = new unsigned char[ pick_texture_width * pick_texture_height * pick_texture_depth ];
- for( int y = 0; y < pick_texture_height; ++y )
- {
- for( int x = 0; x < pick_texture_width * pick_texture_depth ; x += pick_texture_depth )
- {
- unsigned long bits = 0L;
- bits |= ( id << 20 ) | ( y << 10 ) | ( x / 3 );
- unsigned char r_component = ( bits >> 16 ) & 0xff;
- unsigned char g_component = ( bits >> 8 ) & 0xff;
- unsigned char b_component = bits & 0xff;
-
- ptr[ y * pick_texture_width * pick_texture_depth + x + 0 ] = r_component;
- ptr[ y * pick_texture_width * pick_texture_depth + x + 1 ] = g_component;
- ptr[ y * pick_texture_width * pick_texture_depth + x + 2 ] = b_component;
- };
- };
-
- glGenTextures( 1, texture_handle );
-
- checkGLError("glGenTextures");
- std::cout << "glGenTextures returned " << *texture_handle << std::endl;
-
- bindTexture( *texture_handle );
- glTexImage2D( GL_TEXTURE_2D, 0,
- GL_RGB,
- pick_texture_width, pick_texture_height,
- 0, GL_RGB, GL_UNSIGNED_BYTE, ptr );
-
- *texture_pixels = ptr;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-std::string LLMediaPluginTest::mimeTypeFromUrl( std::string& url )
-{
- // default to web
- std::string mime_type = "text/html";
-
- // we may need a more advanced MIME type accessor later :-)
- if ( url.find( ".mov" ) != std::string::npos ) // Movies
- mime_type = "video/quicktime";
- else
- if ( url.find( ".txt" ) != std::string::npos ) // Apple Text descriptors
- mime_type = "video/quicktime";
- else
- if ( url.find( ".mp3" ) != std::string::npos ) // Apple Text descriptors
- mime_type = "video/quicktime";
- else
- if ( url.find( "example://" ) != std::string::npos ) // Example plugin
- mime_type = "example/example";
-
- return mime_type;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-std::string LLMediaPluginTest::pluginNameFromMimeType( std::string& mime_type )
-{
-#if LL_DARWIN
- std::string plugin_name( "media_plugin_null.dylib" );
- if ( mime_type == "video/quicktime" )
- plugin_name = "media_plugin_quicktime.dylib";
- else
- if ( mime_type == "text/html" )
- plugin_name = "media_plugin_webkit.dylib";
-
-#elif LL_WINDOWS
- std::string plugin_name( "media_plugin_null.dll" );
-
- if ( mime_type == "video/quicktime" )
- plugin_name = "media_plugin_quicktime.dll";
- else
- if ( mime_type == "text/html" )
- plugin_name = "media_plugin_webkit.dll";
- else
- if ( mime_type == "example/example" )
- plugin_name = "media_plugin_example.dll";
-
-#elif LL_LINUX
- std::string plugin_name( "libmedia_plugin_null.so" );
-
- if ( mime_type == "video/quicktime" )
- plugin_name = "libmedia_plugin_quicktime.so";
- else
- if ( mime_type == "text/html" )
- plugin_name = "libmedia_plugin_webkit.so";
-#endif
- return plugin_name;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-mediaPanel* LLMediaPluginTest::addMediaPanel( std::string url )
-{
- // Get the plugin filename using the URL
- std::string mime_type = mimeTypeFromUrl( url );
- std::string plugin_name = pluginNameFromMimeType( mime_type );
-
- // create a random size for the new media
- int media_width;
- int media_height;
- getRandomMediaSize( media_width, media_height, mime_type );
-
- // make a new plugin
- LLPluginClassMedia* media_source = new LLPluginClassMedia(this);
-
- // tell the plugin what size we asked for
- media_source->setSize( media_width, media_height );
-
- // Use the launcher start and initialize the plugin
-#if LL_DARWIN || LL_LINUX
- std::string launcher_name( "SLPlugin" );
-#elif LL_WINDOWS
- std::string launcher_name( "SLPlugin.exe" );
-#endif
-
- // for this test app, use the cwd as the user data path (ugh).
-#if LL_WINDOWS
- std::string user_data_path = ".\\";
-#else
- char cwd[ FILENAME_MAX ];
- if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
- {
- std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl;
- return NULL;
- }
- std::string user_data_path = std::string( cwd ) + "/";
-#endif
- media_source->setUserDataPath(user_data_path);
- media_source->init( launcher_name, user_data_path, plugin_name, false );
- media_source->setDisableTimeout(mDisableTimeout);
-
- // make a new panel and save parameters
- mediaPanel* panel = new mediaPanel;
- panel->mMediaSource = media_source;
- panel->mStartUrl = url;
- panel->mMimeType = mime_type;
- panel->mMediaWidth = media_width;
- panel->mMediaHeight = media_height;
- panel->mTextureWidth = 0;
- panel->mTextureHeight = 0;
- panel->mTextureScaleX = 0;
- panel->mTextureScaleY = 0;
- panel->mMediaTextureHandle = 0;
- panel->mPickTextureHandle = 0;
- panel->mAppTextureCoordsOpenGL = false; // really need an 'undefined' state here too
- panel->mReadyToRender = false;
-
- // look through current media panels to find an unused index number
- bool id_exists = true;
- for( int nid = 0; nid < mMaxPanels; ++nid )
- {
- // does this id exist already?
- id_exists = false;
- for( int pid = 0; pid < (int)mMediaPanels.size(); ++pid )
- {
- if ( nid == mMediaPanels[ pid ]->mId )
- {
- id_exists = true;
- break;
- };
- };
-
- // id wasn't found so we can use it
- if ( ! id_exists )
- {
- panel->mId = nid;
- break;
- };
- };
-
- // if we get here and this flag is set, there is no room for any more panels
- if ( id_exists )
- {
- std::cout << "No room for any more panels" << std::endl;
- }
- else
- {
- // now we have the ID we can use it to make the
- // pick texture (id is baked into texture pixels)
- makePickTexture( panel->mId, &panel->mPickTextureHandle, &panel->mPickTexturePixels );
-
- // save this in the list of panels
- mMediaPanels.push_back( panel );
-
- // select the panel that was just created
- selectPanel( panel );
-
- // load and start the URL
- panel->mMediaSource->loadURI( url );
- panel->mMediaSource->start();
-
- std::cout << "Adding new media panel for " << url << "(" << media_width << "x" << media_height << ") with index " << panel->mId << " - total panels = " << mMediaPanels.size() << std::endl;
- }
-
- return panel;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::updateMediaPanel( mediaPanel* panel )
-{
-// checkGLError("LLMediaPluginTest::updateMediaPanel");
-
- if ( ! panel )
- return;
-
- if(!panel->mMediaSource || !panel->mMediaSource->textureValid())
- {
- panel->mReadyToRender = false;
- return;
- }
-
- // take a reference copy of the plugin values since they
- // might change during this lifetime of this function
- int plugin_media_width = panel->mMediaSource->getWidth();
- int plugin_media_height = panel->mMediaSource->getHeight();
- int plugin_texture_width = panel->mMediaSource->getBitsWidth();
- int plugin_texture_height = panel->mMediaSource->getBitsHeight();
-
- // If the texture isn't created or the media or texture dimensions changed AND
- // the sizes are valid then we need to delete the old media texture (if necessary)
- // then make a new one.
- if ((panel->mMediaTextureHandle == 0 ||
- panel->mMediaWidth != plugin_media_width ||
- panel->mMediaHeight != plugin_media_height ||
- panel->mTextureWidth != plugin_texture_width ||
- panel->mTextureHeight != plugin_texture_height) &&
- ( plugin_media_width > 0 && plugin_media_height > 0 &&
- plugin_texture_width > 0 && plugin_texture_height > 0 ) )
- {
- std::cout << "Valid media size (" << plugin_media_width << " x " << plugin_media_height
- << ") and texture size (" << plugin_texture_width << " x " << plugin_texture_height
- << ") for panel with ID=" << panel->mId << " - making texture" << std::endl;
-
- // delete old GL texture
- if ( isTexture( panel->mMediaTextureHandle ) )
- {
- std::cerr << "updateMediaPanel: deleting texture " << panel->mMediaTextureHandle << std::endl;
- glDeleteTextures( 1, &panel->mMediaTextureHandle );
- panel->mMediaTextureHandle = 0;
- }
-
- std::cerr << "before: pick texture is " << panel->mPickTextureHandle << ", media texture is " << panel->mMediaTextureHandle << std::endl;
-
- // make a GL texture based on the dimensions the plugin told us
- GLuint new_texture = 0;
- glGenTextures( 1, &new_texture );
-
- checkGLError("glGenTextures");
-
- std::cout << "glGenTextures returned " << new_texture << std::endl;
-
- panel->mMediaTextureHandle = new_texture;
-
- bindTexture( panel->mMediaTextureHandle );
-
- std::cout << "Setting texture size to " << plugin_texture_width << " x " << plugin_texture_height << std::endl;
- glTexImage2D( GL_TEXTURE_2D, 0,
- GL_RGB,
- plugin_texture_width, plugin_texture_height,
- 0, GL_RGB, GL_UNSIGNED_BYTE,
- 0 );
-
-
- std::cerr << "after: pick texture is " << panel->mPickTextureHandle << ", media texture is " << panel->mMediaTextureHandle << std::endl;
- };
-
- // update our record of the media and texture dimensions
- // NOTE: do this after we we check for sizes changes
- panel->mMediaWidth = plugin_media_width;
- panel->mMediaHeight = plugin_media_height;
- panel->mTextureWidth = plugin_texture_width;
- panel->mTextureHeight = plugin_texture_height;
- if ( plugin_texture_width > 0 )
- {
- panel->mTextureScaleX = (double)panel->mMediaWidth / (double)panel->mTextureWidth;
- };
- if ( plugin_texture_height > 0 )
- {
- panel->mTextureScaleY = (double)panel->mMediaHeight / (double)panel->mTextureHeight;
- };
-
- // update the flag which tells us if the media source uses OprnGL coords or not.
- panel->mAppTextureCoordsOpenGL = panel->mMediaSource->getTextureCoordsOpenGL();
-
- // Check to see if we have enough to render this panel.
- // If we do, set a flag that the display functions use so
- // they only render a panel with media if it's ready.
- if ( panel->mMediaWidth < 0 ||
- panel->mMediaHeight < 0 ||
- panel->mTextureWidth < 1 ||
- panel->mTextureHeight < 1 ||
- panel->mMediaTextureHandle == 0 )
- {
- panel->mReadyToRender = false;
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-mediaPanel* LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url )
-{
- // no media panels so we can't change anything - have to add
- if ( mMediaPanels.size() == 0 )
- return NULL;
-
- // sanity check
- if ( ! panel )
- return NULL;
-
- int index;
- for(index = 0; index < (int)mMediaPanels.size(); index++)
- {
- if(mMediaPanels[index] == panel)
- break;
- }
-
- if(index >= (int)mMediaPanels.size())
- {
- // panel isn't in mMediaPanels
- return NULL;
- }
-
- std::cout << "Replacing media panel with index " << panel->mId << std::endl;
-
- int panel_id = panel->mId;
-
- if(mSelectedPanel == panel)
- mSelectedPanel = NULL;
-
- delete panel;
-
- // Get the plugin filename using the URL
- std::string mime_type = mimeTypeFromUrl( url );
- std::string plugin_name = pluginNameFromMimeType( mime_type );
-
- // create a random size for the new media
- int media_width;
- int media_height;
- getRandomMediaSize( media_width, media_height, mime_type );
-
- // make a new plugin
- LLPluginClassMedia* media_source = new LLPluginClassMedia(this);
-
- // tell the plugin what size we asked for
- media_source->setSize( media_width, media_height );
-
- // Use the launcher start and initialize the plugin
-#if LL_DARWIN || LL_LINUX
- std::string launcher_name( "SLPlugin" );
-#elif LL_WINDOWS
- std::string launcher_name( "SLPlugin.exe" );
-#endif
-
- // for this test app, use the cwd as the user data path (ugh).
-#if LL_WINDOWS
- std::string user_data_path = ".\\";
-#else
- char cwd[ FILENAME_MAX ];
- if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
- {
- std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl;
- return NULL;
- }
- std::string user_data_path = std::string( cwd ) + "/";
-#endif
-
- media_source->setUserDataPath(user_data_path);
- media_source->init( launcher_name, user_data_path, plugin_name, false );
- media_source->setDisableTimeout(mDisableTimeout);
-
- // make a new panel and save parameters
- panel = new mediaPanel;
- panel->mMediaSource = media_source;
- panel->mStartUrl = url;
- panel->mMimeType = mime_type;
- panel->mMediaWidth = media_width;
- panel->mMediaHeight = media_height;
- panel->mTextureWidth = 0;
- panel->mTextureHeight = 0;
- panel->mTextureScaleX = 0;
- panel->mTextureScaleY = 0;
- panel->mMediaTextureHandle = 0;
- panel->mPickTextureHandle = 0;
- panel->mAppTextureCoordsOpenGL = false; // really need an 'undefined' state here too
- panel->mReadyToRender = false;
-
- panel->mId = panel_id;
-
- // Replace the entry in the panels array
- mMediaPanels[index] = panel;
-
- // now we have the ID we can use it to make the
- // pick texture (id is baked into texture pixels)
- makePickTexture( panel->mId, &panel->mPickTextureHandle, &panel->mPickTexturePixels );
-
- // select the panel that was just created
- selectPanel( panel );
-
- // load and start the URL
- panel->mMediaSource->loadURI( url );
- panel->mMediaSource->start();
-
- return panel;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::getRandomMediaSize( int& width, int& height, std::string mime_type )
-{
- // Make a new media source with a random size which we'll either
- // directly or the media plugin will tell us what it wants later.
- // Use a random size so we can test support for weird media sizes.
- // (Almost everything else will get filled in later once the
- // plugin responds)
- // NB. Do we need to enforce that width is on 4 pixel boundary?
- width = ( ( rand() % 170 ) + 30 ) * 4;
- height = ( ( rand() % 170 ) + 30 ) * 4;
-
- // adjust this random size if it's a browser so we get
- // a more useful size for testing..
- if ( mime_type == "text/html" || mime_type == "example/example" )
- {
- width = ( ( rand() % 100 ) + 100 ) * 4;
- height = ( width * ( ( rand() % 400 ) + 1000 ) ) / 1000;
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::remMediaPanel( mediaPanel* panel )
-{
- // always leave one panel
- if ( mMediaPanels.size() == 1 )
- return;
-
- // sanity check - don't think this can happen but see above for a case where it might...
- if ( ! panel )
- return;
-
- std::cout << "Removing media panel with index " << panel->mId << " - total panels = " << mMediaPanels.size() - 1 << std::endl;
-
- if(mSelectedPanel == panel)
- mSelectedPanel = NULL;
-
- delete panel;
-
- // remove from storage list
- for( int i = 0; i < (int)mMediaPanels.size(); ++i )
- {
- if ( mMediaPanels[ i ] == panel )
- {
- mMediaPanels.erase( mMediaPanels.begin() + i );
- break;
- };
- };
-
- // select the first panel
- selectPanel( mMediaPanels[ 0 ] );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::updateStatusBar()
-{
- if ( ! mSelectedPanel )
- return;
-
- // cache results - this is a very slow function
- static int cached_id = -1;
- static int cached_media_width = -1;
- static int cached_media_height = -1;
- static int cached_texture_width = -1;
- static int cached_texture_height = -1;
- static bool cached_supports_browser_media = true;
- static bool cached_supports_time_media = false;
- static int cached_movie_time = -1;
- static GLfloat cached_distance = -1.0f;
-
- static std::string cached_plugin_version = "";
- if (
- cached_id == mSelectedPanel->mId &&
- cached_media_width == mSelectedPanel->mMediaWidth &&
- cached_media_height == mSelectedPanel->mMediaHeight &&
- cached_texture_width == mSelectedPanel->mTextureWidth &&
- cached_texture_height == mSelectedPanel->mTextureHeight &&
- cached_supports_browser_media == mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() &&
- cached_supports_time_media == mSelectedPanel->mMediaSource->pluginSupportsMediaTime() &&
- cached_plugin_version == mSelectedPanel->mMediaSource->getPluginVersion() &&
- cached_movie_time == (int)mSelectedPanel->mMediaSource->getCurrentTime() &&
- cached_distance == mDistanceCameraToSelectedGeometry
- )
- {
- // nothing changed so don't spend time here
- return;
- };
-
- std::ostringstream stream( "" );
-
- stream.str( "" );
- stream.clear();
-
- stream << "Id: ";
- stream << std::setw( 2 ) << std::setfill( '0' );
- stream << mSelectedPanel->mId;
- stream << " | ";
- stream << "Media: ";
- stream << std::setw( 3 ) << std::setfill( '0' );
- stream << mSelectedPanel->mMediaWidth;
- stream << " x ";
- stream << std::setw( 3 ) << std::setfill( '0' );
- stream << mSelectedPanel->mMediaHeight;
- stream << " | ";
- stream << "Texture: ";
- stream << std::setw( 4 ) << std::setfill( '0' );
- stream << mSelectedPanel->mTextureWidth;
- stream << " x ";
- stream << std::setw( 4 ) << std::setfill( '0' );
- stream << mSelectedPanel->mTextureHeight;
-
- stream << " | ";
- stream << "Distance: ";
- stream << std::setw( 6 );
- stream << std::setprecision( 3 );
- stream << std::setprecision( 3 );
- stream << mDistanceCameraToSelectedGeometry;
- stream << " | ";
-
- if ( mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() )
- stream << "BROWSER";
- else
- if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() )
- stream << "TIME ";
- stream << " | ";
- stream << mSelectedPanel->mMediaSource->getPluginVersion();
- stream << " | ";
- if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() )
- {
- stream << std::setw( 3 ) << std::setfill( '0' );
- stream << (int)mSelectedPanel->mMediaSource->getCurrentTime();
- stream << " / ";
- stream << std::setw( 3 ) << std::setfill( '0' );
- stream << (int)mSelectedPanel->mMediaSource->getDuration();
- stream << " @ ";
- stream << (int)mSelectedPanel->mMediaSource->getCurrentPlayRate();
- stream << " | ";
- };
-
- glutSetWindow( mBottomGLUIWindow->get_glut_window_id() );
- mStatusText->set_text( const_cast< char*>( stream.str().c_str() ) );
- glutSetWindow( mAppWindow );
-
- // caching
- cached_id = mSelectedPanel->mId;
- cached_media_width = mSelectedPanel->mMediaWidth;
- cached_media_height = mSelectedPanel->mMediaHeight;
- cached_texture_width = mSelectedPanel->mTextureWidth;
- cached_texture_height = mSelectedPanel->mTextureHeight;
- cached_supports_browser_media = mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser();
- cached_supports_time_media = mSelectedPanel->mMediaSource->pluginSupportsMediaTime();
- cached_plugin_version = mSelectedPanel->mMediaSource->getPluginVersion();
- cached_movie_time = (int)mSelectedPanel->mMediaSource->getCurrentTime();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::dumpPanelInfo()
-{
- std::cout << std::endl << "===== Media Panels =====" << std::endl;
- for( int i = 0; i < (int)mMediaPanels.size(); ++i )
- {
- std::cout << std::setw( 2 ) << std::setfill( '0' );
- std::cout << i + 1 << "> ";
- std::cout << "Id: ";
- std::cout << std::setw( 2 ) << std::setfill( '0' );
- std::cout << mMediaPanels[ i ]->mId;
- std::cout << " | ";
- std::cout << "Media: ";
- std::cout << std::setw( 3 ) << std::setfill( '0' );
- std::cout << mMediaPanels[ i ]->mMediaWidth;
- std::cout << " x ";
- std::cout << std::setw( 3 ) << std::setfill( '0' );
- std::cout << mMediaPanels[ i ]->mMediaHeight;
- std::cout << " | ";
- std::cout << "Texture: ";
- std::cout << std::setw( 4 ) << std::setfill( '0' );
- std::cout << mMediaPanels[ i ]->mTextureWidth;
- std::cout << " x ";
- std::cout << std::setw( 4 ) << std::setfill( '0' );
- std::cout << mMediaPanels[ i ]->mTextureHeight;
- std::cout << " | ";
- if ( mMediaPanels[ i ] == mSelectedPanel )
- std::cout << "(selected)";
-
- std::cout << std::endl;
- };
- std::cout << "========================" << std::endl;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
-{
- // Uncomment this to make things much, much quieter.
-// return;
-
- switch(event)
- {
- case MEDIA_EVENT_CONTENT_UPDATED:
- // too spammy -- don't log these
-// std::cerr << "Media event: MEDIA_EVENT_CONTENT_UPDATED " << std::endl;
- break;
-
- case MEDIA_EVENT_TIME_DURATION_UPDATED:
- // too spammy -- don't log these
-// std::cerr << "Media event: MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << std::endl;
- break;
-
- case MEDIA_EVENT_SIZE_CHANGED:
- std::cerr << "Media event: MEDIA_EVENT_SIZE_CHANGED " << std::endl;
- break;
-
- case MEDIA_EVENT_CURSOR_CHANGED:
- std::cerr << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << std::endl;
- break;
-
- case MEDIA_EVENT_NAVIGATE_BEGIN:
- std::cerr << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN " << std::endl;
- break;
-
- case MEDIA_EVENT_NAVIGATE_COMPLETE:
- std::cerr << "Media event: MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << std::endl;
- break;
-
- case MEDIA_EVENT_PROGRESS_UPDATED:
- std::cerr << "Media event: MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << std::endl;
- break;
-
- case MEDIA_EVENT_STATUS_TEXT_CHANGED:
- std::cerr << "Media event: MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << std::endl;
- break;
-
- case MEDIA_EVENT_NAME_CHANGED:
- std::cerr << "Media event: MEDIA_EVENT_NAME_CHANGED, new name is: " << self->getMediaName() << std::endl;
- glutSetWindowTitle( self->getMediaName().c_str() );
- break;
-
- case MEDIA_EVENT_LOCATION_CHANGED:
- {
- std::cerr << "Media event: MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << std::endl;
- mediaPanel* panel = findMediaPanel(self);
- if(panel != NULL)
- {
- panel->mStartUrl = self->getLocation();
- if(panel == mSelectedPanel)
- {
- mUrlEdit->set_text(const_cast<char*>(panel->mStartUrl.c_str()) );
- }
- }
- }
- break;
-
- case MEDIA_EVENT_NAVIGATE_ERROR_PAGE:
- std::cerr << "Media event: MEDIA_EVENT_NAVIGATE_ERROR_PAGE, uri is: " << self->getClickURL() << std::endl;
- break;
-
- case MEDIA_EVENT_CLICK_LINK_HREF:
- {
- std::cerr << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, uri is " << self->getClickURL() << ", target is " << self->getClickTarget() << std::endl;
- // retrieve the event parameters
- std::string url = self->getClickURL();
- std::string target = self->getClickTarget();
-
- if(target == "_external")
- {
- // this should open in an external browser, but since this is a test app we don't care.
- }
- else if(target == "_blank")
- {
- // Create a new panel with the specified URL.
- addMediaPanel(url);
- }
- else // other named target
- {
- mediaPanel *target_panel = findMediaPanel(target);
- if(target_panel)
- {
- target_panel = replaceMediaPanel(target_panel, url);
- }
- else
- {
- target_panel = addMediaPanel(url);
- }
-
- if(target_panel)
- {
- target_panel->mTarget = target;
- }
- }
- }
- break;
-
- case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
- std::cerr << "Media event: MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << std::endl;
- break;
-
- case MEDIA_EVENT_PLUGIN_FAILED:
- std::cerr << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << std::endl;
- break;
-
- case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
- std::cerr << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << std::endl;
- break;
-
- case MEDIA_EVENT_CLOSE_REQUEST:
- std::cerr << "Media event: MEDIA_EVENT_CLOSE_REQUEST" << std::endl;
- break;
-
- case MEDIA_EVENT_PICK_FILE_REQUEST:
- std::cerr << "Media event: MEDIA_EVENT_PICK_FILE_REQUEST" << std::endl;
- // TODO: display an actual file picker
- self->sendPickFileResponse("cake");
- break;
-
- case MEDIA_EVENT_GEOMETRY_CHANGE:
- std::cerr << "Media event: MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID()
- << ", x = " << self->getGeometryX()
- << ", y = " << self->getGeometryY()
- << ", width = " << self->getGeometryWidth()
- << ", height = " << self->getGeometryHeight()
- << std::endl;
- break;
-
- case MEDIA_EVENT_AUTH_REQUEST:
- {
- //std::cerr << "Media event: MEDIA_EVENT_AUTH_REQUEST, url " << self->getAuthURL() ", realm " << self->getAuthRealm() << std::endl;
-
- // TODO: display an auth dialog
- self->sendAuthResponse(false, "", "");
- }
- break;
-
- case MEDIA_EVENT_LINK_HOVERED:
- {
- std::cerr << "Media event: MEDIA_EVENT_LINK_HOVERED, hover text is: " << self->getHoverText() << std::endl;
- }
- break;
-
- default:
- {
- std::cerr << "Media event: <unknown>, code is: " << int(event) << std::endl;
- }
- break;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-static void gluiCallbackWrapper( int control_id )
-{
- if ( gApplication )
- gApplication->gluiCallback( control_id );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void glutReshape( int width, int height )
-{
- if ( gApplication )
- gApplication->reshape( width, height );
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void glutDisplay()
-{
- if ( gApplication )
- gApplication->display();
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void glutIdle(int update_ms)
-{
- GLUI_Master.set_glutTimerFunc( update_ms, glutIdle, update_ms);
-
- if ( gApplication )
- gApplication->idle();
-
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void glutKeyboard( unsigned char key, int x, int y )
-{
- if ( gApplication )
- gApplication->keyboard( key );
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void glutMousePassive( int x, int y )
-{
- if ( gApplication )
- gApplication->mousePassive( x, y );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void glutMouseMove( int x , int y )
-{
- if ( gApplication )
- gApplication->mouseMove( x, y );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void glutMouseButton( int button, int state, int x, int y )
-{
- if ( gApplication )
- gApplication->mouseButton( button, state, x, y );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-int main( int argc, char* argv[] )
-{
-#if LL_DARWIN
- // Set the current working directory to <application bundle>/Contents/Resources/
- CFURLRef resources_url = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
- if(resources_url != NULL)
- {
- CFStringRef resources_string = CFURLCopyFileSystemPath(resources_url, kCFURLPOSIXPathStyle);
- CFRelease(resources_url);
- if(resources_string != NULL)
- {
- char buffer[PATH_MAX] = "";
- if(CFStringGetCString(resources_string, buffer, sizeof(buffer), kCFStringEncodingUTF8))
- {
- chdir(buffer);
- }
- CFRelease(resources_string);
- }
- }
-#endif
-
- glutInit( &argc, argv );
- glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB );
-
- const int app_window_x = 80;
- const int app_window_y = 0;
- const int app_window_width = 960;
- const int app_window_height = 960;
-
- glutInitWindowPosition( app_window_x, app_window_y );
- glutInitWindowSize( app_window_width, app_window_height );
-
- int app_window_handle = glutCreateWindow( "LLMediaPluginTest" );
-
- glutDisplayFunc( glutDisplay );
-
- GLUI_Master.set_glutReshapeFunc( glutReshape );
- GLUI_Master.set_glutKeyboardFunc( glutKeyboard );
- GLUI_Master.set_glutMouseFunc( glutMouseButton );
-
- glutPassiveMotionFunc( glutMousePassive );
- glutMotionFunc( glutMouseMove );
-
- glutSetWindow( app_window_handle );
-
- gApplication = new LLMediaPluginTest( app_window_handle, app_window_width, app_window_height );
-
- // update at approximately 60hz
- int update_ms = 1000 / 60;
-
- GLUI_Master.set_glutTimerFunc( update_ms, glutIdle, update_ms);
-
- glutMainLoop();
-
- delete gApplication;
-}
diff --git a/indra/test_apps/llplugintest/llmediaplugintest.h b/indra/test_apps/llplugintest/llmediaplugintest.h
deleted file mode 100755
index 1f6f18e43c..0000000000
--- a/indra/test_apps/llplugintest/llmediaplugintest.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/**
- * @file LLMediaPluginTest.cpp
- * @brief Primary test application for LLMedia (Separate Process) Plugin system
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_MEDIA_PLUGIN_TEST_H
-#define LL_MEDIA_PLUGIN_TEST_H
-
-#include <vector>
-#include <string>
-#include "llpluginclassmedia.h"
-#include "llgl.h"
-
-// Forward declarations
-class GLUI_Rotation;
-class GLUI_Translation;
-class GLUI_Listbox;
-class GLUI_EditText;
-class GLUI_StaticText;
-class GLUI;
-class GLUI_Button;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-struct mediaPanel
-{
- public:
- mediaPanel();
- ~mediaPanel();
- int mId;
- std::string mStartUrl;
- std::string mMimeType;
- std::string mTarget;
- LLPluginClassMedia *mMediaSource;
- int mMediaWidth;
- int mMediaHeight;
- int mTextureWidth;
- int mTextureHeight;
- double mTextureScaleX;
- double mTextureScaleY;
- GLuint mMediaTextureHandle;
- GLuint mPickTextureHandle;
- unsigned char* mPickTexturePixels;
- bool mAppTextureCoordsOpenGL;
- bool mReadyToRender;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-class LLMediaPluginTest : public LLPluginClassMediaOwner
-{
- public:
- LLMediaPluginTest( int app_window, int window_width, int window_height );
- ~LLMediaPluginTest();
-
- void reshape( int width, int height );
- void display();
- void idle();
- void gluiCallback( int control_id );
- void keyboard( int key );
- void mousePassive( int x, int y );
- void mouseButton( int button, int state, int x, int y );
- void mouseMove( int x, int y );
-
- void bindTexture(GLuint texture, GLint row_length = 0, GLint alignment = 1);
- bool checkGLError(const char *name = "OpenGL");
- void drawGeometry( int panel, bool selected );
- void startPanelHighlight( float red, float green, float blue, float line_width );
- void endPanelHighlight();
- enum { DrawTypePickTexture, DrawTypeMediaTexture };
- void draw( int draw_type );
- void windowPosToTexturePos( int window_x, int window_y, int& media_x, int& media_y, int& id );
-
- mediaPanel* addMediaPanel( std::string url );
- void updateMediaPanel( mediaPanel* panel );
- void remMediaPanel( mediaPanel* panel );
- mediaPanel* replaceMediaPanel( mediaPanel* panel, std::string url );
- void getRandomMediaSize( int& width, int& height, std::string mime_type );
- void navigateToNewURI( std::string uri );
- void initUrlHistory( std::string uri );
- void selectPanelById( int id );
- void selectPanel( mediaPanel* panel );
- mediaPanel* findMediaPanel( LLPluginClassMedia* panel );
- mediaPanel* findMediaPanel( const std::string &target_name );
- void makePickTexture( int id, GLuint* texture_handle, unsigned char** texture_pixels );
- void makeChrome();
- void resetView();
-
- void dumpPanelInfo();
- void updateStatusBar();
-
- GLfloat distanceToCamera( GLfloat point_x, GLfloat point_y, GLfloat point_z );
-
-
- // Inherited from LLPluginClassMediaOwner
- /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent);
-
- private:
- const int mVersionMajor;
- const int mVersionMinor;
- const int mVersionPatch;
- const int mMaxPanels;
- int mAppWindow;
- int mWindowWidth;
- int mWindowHeight;
- int mCurMouseX;
- int mCurMouseY;
- unsigned char mPixelReadColor[ 3 ];
- bool mFuzzyMedia;
- const std::string mHomeWebUrl;
-
- std::vector< mediaPanel* > mMediaPanels;
- mediaPanel* mSelectedPanel;
- std::string mimeTypeFromUrl( std::string& url );
- std::string pluginNameFromMimeType( std::string& mime_type );
-
- GLUI_Rotation* mViewRotationCtrl;
- GLUI_Translation* mViewScaleCtrl;
- GLUI_Translation* mViewTranslationCtrl;
- float mViewportAspect;
- float mViewPos[ 3 ];
- float mViewRotation[ 16 ];
-
- float mDistanceCameraToSelectedGeometry;
-
- int mIdControlAddPanel;
- int mIdControlRemPanel;
-
- std::vector< std::pair< std::string, std::string > > mBookmarks;
- GLUI_Listbox* mBookmarkList;
- int mIdBookmarks;
- int mIdUrlEdit;
- GLUI_EditText* mUrlEdit;
- int mIdUrlInitHistoryEdit;
- GLUI_EditText* mUrlInitHistoryEdit;
- int mSelBookmark;
- int mIdRandomPanelCount;
- int mRandomPanelCount;
- int mIdRandomBookmarks;
- int mRandomBookmarks;
- int mIdDisableTimeout;
- int mDisableTimeout;
- int mIdUsePluginReadThread;
- int mUsePluginReadThread;
- int mIdLargePanelSpacing;
- int mLargePanelSpacing;
- int mIdControlCrashPlugin;
- int mIdControlHangPlugin;
- int mIdControlExitApp;
-
- GLUI* mGluiMediaTimeControlWindow;
- int mIdMediaTimeControlPlay;
- int mIdMediaTimeControlLoop;
- int mIdMediaTimeControlPause;
- int mIdMediaTimeControlStop;
- int mIdMediaTimeControlSeek;
- int mIdMediaTimeControlVolume;
- int mMediaTimeControlVolume;
- int mIdMediaTimeControlSeekSeconds;
- int mMediaTimeControlSeekSeconds;
- int mIdMediaTimeControlRewind;
- int mIdMediaTimeControlFastForward;
-
- GLUI* mGluiMediaBrowserControlWindow;
- int mIdMediaBrowserControlBack;
- GLUI_Button* mMediaBrowserControlBackButton;
- int mIdMediaBrowserControlStop;
- int mIdMediaBrowserControlForward;
- GLUI_Button* mMediaBrowserControlForwardButton;
- bool mGluiMediaTimeControlWindowFlag;
- bool mGluiMediaBrowserControlWindowFlag;
- bool mMediaBrowserControlBackButtonFlag;
- bool mMediaBrowserControlForwardButtonFlag;
- int mIdMediaBrowserControlHome;
- int mIdMediaBrowserControlReload;
- int mIdMediaBrowserControlClearCache;
- int mIdMediaBrowserControlClearCookies;
- int mIdMediaBrowserControlEnableCookies;
- int mMediaBrowserControlEnableCookies;
-
- GLUI* mBottomGLUIWindow;
- GLUI_StaticText* mStatusText;
-};
-
-#endif // LL_MEDIA_PLUGIN_TEST_H
-