diff options
| author | AndreyL ProductEngine <alihatskiy@productengine.com> | 2015-12-22 17:59:01 +0200 | 
|---|---|---|
| committer | AndreyL ProductEngine <alihatskiy@productengine.com> | 2015-12-22 17:59:01 +0200 | 
| commit | b095e2c985680660d61a99e8dbac78d9113b9870 (patch) | |
| tree | 171d31162fcb58f05c440de7ae383c7a88819a43 | |
| parent | 49fa9b5515e708083c85aaa2b1b522bc266944c4 (diff) | |
| parent | 60dfd55edaa5df0cb864dc5086037bc5625bc0be (diff) | |
Merge
85 files changed, 2675 insertions, 9134 deletions
@@ -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 aeea3b1246..15fb56ec17 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 52d750f64d..824bf4b690 100755 --- a/autobuild.xml +++ b/autobuild.xml @@ -1517,16 +1517,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> @@ -1534,44 +1536,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> @@ -1580,7 +1572,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> @@ -1588,11 +1580,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> @@ -1602,9 +1594,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> @@ -1614,29 +1606,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> @@ -1644,11 +1634,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> @@ -1658,11 +1648,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> @@ -1672,18 +1660,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> @@ -2052,9 +2038,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> @@ -2063,62 +2049,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 cd7da5d6c1..4dd69649d0 100755 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -14,6 +14,7 @@ set(cmake_SOURCE_FILES      Boost.cmake      BuildVersion.cmake      CARes.cmake +    CEFPlugin.cmake      CMakeCopyIfDifferent.cmake      ConfigurePkgConfig.cmake      CURL.cmake @@ -82,18 +83,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 @@ -102,7 +103,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/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 73df47b933..7e9ae8d108 100755 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -178,6 +178,11 @@ void LLCurl::Responder::setURL(const std::string& url)  	mURL = url;  } +const std::string& LLCurl::Responder::getURL() +{ +	return mURL; +} +  void LLCurl::Responder::successResult(const LLSD& content)  {  	setResult(HTTP_OK, "", content); diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 385d9fffa8..34758433c8 100755 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -147,6 +147,7 @@ public:  	public:  		void setHTTPMethod(EHTTPMethod method);  		void setURL(const std::string& url); +		const std::string& getURL();  		void setResult(S32 status, const std::string& reason, const LLSD& content = LLSD());  		void setResponseHeader(const std::string& header, const std::string& value); 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 fcf5d912f4..05483c4608 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} @@ -1769,44 +1765,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        ) @@ -1851,10 +1815,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) @@ -2021,9 +1985,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      ) @@ -2135,7 +2098,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) @@ -2190,20 +2153,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 5f378c64e8..1fdfdb51a8 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> @@ -3788,7 +3788,7 @@        <string>Boolean</string>        <key>Value</key>        <integer>0</integer> -    </map>	 +    </map>  	<key>FirstSelectedEnabledPopups</key>      <map>        <key>Comment</key> @@ -3799,7 +3799,7 @@        <string>Boolean</string>        <key>Value</key>        <integer>0</integer> -    </map>		 +    </map>      <key>FixedWeather</key>      <map>        <key>Comment</key> @@ -3921,7 +3921,7 @@        <key>Value</key>        <string>SW</string>      </map> -   +      <key>FloaterStatisticsRect</key>      <map>        <key>Comment</key> @@ -4448,7 +4448,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> @@ -4514,7 +4514,7 @@        <string>Boolean</string>        <key>Value</key>        <integer>0</integer> -    </map>	 +    </map>      <key>HostID</key>      <map>        <key>Comment</key> @@ -4602,7 +4602,7 @@        <string>Boolean</string>        <key>Value</key>        <integer>0</integer> -    </map>   +    </map>      <key>IgnorePixelDepth</key>      <map>        <key>Comment</key> @@ -4657,7 +4657,7 @@        <string>F32</string>        <key>Value</key>        <real>0.5</real> -    </map>  +    </map>  	<key>InspectorShowTime</key>      <map>        <key>Comment</key> @@ -4668,7 +4668,7 @@        <string>F32</string>        <key>Value</key>        <real>3.0</real> -    </map>  +    </map>      <key>InstallLanguage</key>      <map>        <key>Comment</key> @@ -5230,7 +5230,7 @@        <key>Value</key>        <string>0.0.0</string>      </map> -   +      <key>LastSnapshotToProfileHeight</key>      <map>        <key>Comment</key> @@ -6309,7 +6309,7 @@        <string>Boolean</string>        <key>Value</key>        <integer>0</integer> -    </map>   +    </map>      <key>MenuAccessKeyTime</key>      <map>        <key>Comment</key> @@ -6474,7 +6474,7 @@        <string>Boolean</string>        <key>Value</key>        <integer>0</integer> -    </map>  +    </map>      <key>MouseSun</key>      <map>        <key>Comment</key> @@ -6639,7 +6639,7 @@        <string>String</string>        <key>Value</key>        <string /> -    </map>	 +    </map>      <key>NextLoginLocation</key>      <map>        <key>Comment</key> @@ -6763,7 +6763,7 @@        <string>String</string>        <key>Value</key>        <string>toast</string> -    </map>   +    </map>      <key>NotificationFriendIMOptions</key>      <map>        <key>Comment</key> @@ -6819,7 +6819,7 @@        <string>String</string>        <key>Value</key>        <string>toast</string> -    </map>   +    </map>      <key>NotificationObjectIMOptions</key>      <map>        <key>Comment</key> @@ -6833,7 +6833,7 @@        <string>String</string>        <key>Value</key>        <string>toast</string> -    </map>   +    </map>      <key>NotificationToastLifeTime</key>      <map>        <key>Comment</key> @@ -7392,7 +7392,7 @@        <string>Boolean</string>        <key>Value</key>        <integer>0</integer> -    </map>   +    </map>      <key>PlaySoundFriendIM</key>      <map>        <key>Comment</key> @@ -7503,7 +7503,7 @@        <key>Value</key>        <real>0.9</real>      </map> -     +     <key>PlainTextChatHistory</key>      <map>        <key>Comment</key> @@ -7515,7 +7515,7 @@        <key>Value</key>        <integer>0</integer>      </map> -     +      <key>PluginInstancesLow</key>      <map>        <key>Comment</key> @@ -7769,7 +7769,7 @@        <real>0.4</real>      </array>    </map> -   +    <key>PreviewDirection2</key>    <map>      <key>Comment</key> @@ -8081,7 +8081,7 @@      <key>Type</key>      <string>F32</string>      <key>Value</key> -    <real>5.0</real> +    <real>10.0</real>    </map>    <key>MediaRollOffMax</key>    <map> @@ -8379,7 +8379,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> @@ -8457,7 +8457,7 @@        <key>Value</key>        <integer>0</integer>      </map> -    +    <key>RenderLocalLights</key>    <map>      <key>Comment</key> @@ -8684,7 +8684,7 @@        <key>Persist</key>        <integer>1</integer>        <key>Type</key> -      <string>Boolean</string>  +      <string>Boolean</string>        <key>Value</key>        <integer>0</integer>      </map> @@ -8721,7 +8721,7 @@      <key>Value</key>      <integer>0</integer>    </map> -  +    <key>RenderAnimateRes</key>    <map>      <key>Comment</key> @@ -8894,7 +8894,7 @@      <key>Value</key>      <integer>0</integer>    </map> -   +    <key>RenderDepthOfField</key>    <map>      <key>Comment</key> @@ -9023,7 +9023,7 @@      <key>Value</key>      <real>0.1</real>    </map> -   +    <key>RenderHighlightBrightness</key>    <map>      <key>Comment</key> @@ -9047,7 +9047,7 @@      <key>Value</key>      <real>0.6</real>    </map> -   +    <key>RenderHighlightColor</key>    <map>      <key>Comment</key> @@ -9076,7 +9076,7 @@      <key>Value</key>      <integer>0</integer>    </map> -   +    <key>RenderSpecularResX</key>    <map>      <key>Comment</key> @@ -9981,7 +9981,7 @@        <key>Value</key>        <integer>1</integer>      </map> -   +    <key>RenderAutoMuteByteLimit</key>    <map>      <key>Comment</key> @@ -10036,7 +10036,7 @@      <string>Boolean</string>      <key>Value</key>      <integer>0</integer> -  </map>     +  </map>    <key>RenderAutoHideSurfaceAreaLimit</key>    <map>      <key>Comment</key> @@ -10522,7 +10522,7 @@        <string>Boolean</string>        <key>Value</key>        <integer>0</integer> -    </map>	 +    </map>      <key>SelectMovableOnly</key>      <map>        <key>Comment</key> @@ -10764,7 +10764,7 @@        <string>Boolean</string>        <key>Value</key>        <integer>1</integer> -    </map>	 +    </map>      <key>ShowCrosshairs</key>      <map>        <key>Comment</key> @@ -10841,7 +10841,7 @@        <string>Boolean</string>        <key>Value</key>        <integer>0</integer> -    </map>     +    </map>      <key>ShowMiniMapButton</key>      <map>        <key>Comment</key> @@ -10908,7 +10908,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> @@ -10917,9 +10917,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> @@ -10928,9 +10928,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> @@ -10939,7 +10939,7 @@        <key>Type</key>        <string>Boolean</string>        <key>Value</key> -      <integer>1</integer>    +      <integer>1</integer>      </map>      <key>ShowWorldMapButton</key>      <map> @@ -11095,7 +11095,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> @@ -11611,7 +11611,7 @@        <string>S32</string>        <key>Value</key>        <integer>0</integer> -    </map>   +    </map>      <key>SnapshotQuality</key>      <map>        <key>Comment</key> @@ -12480,7 +12480,7 @@        <string>String</string>        <key>Value</key>        <string>B56AF90D-6684-48E4-B1E4-722D3DEB2CB6</string> -    </map>   +    </map>      <key>NearByChatChannelUUID</key>      <map>        <key>Comment</key> @@ -12491,7 +12491,7 @@        <string>String</string>        <key>Value</key>        <string>E1158BD6-661C-4981-9DAD-4DCBFF062502</string> -    </map>   +    </map>      <key>NotificationChannelUUID</key>      <map>        <key>Comment</key> @@ -12502,7 +12502,7 @@        <string>String</string>        <key>Value</key>        <string>AEED3193-8709-4693-8558-7452CCA97AE5</string> -    </map>   +    </map>      <key>AlertChannelUUID</key>      <map>        <key>Comment</key> @@ -12513,7 +12513,7 @@        <string>String</string>        <key>Value</key>        <string>F3E07BC8-A973-476D-8C7F-F3B7293975D1</string> -    </map>   +    </map>      <key>UIImgWhiteUUID</key>      <map>        <key>Comment</key> @@ -12535,7 +12535,7 @@        <string>S32</string>        <key>Value</key>        <integer>2</integer> -    </map>  +    </map>      <key>UIMaxComboWidth</key>      <map>        <key>Comment</key> @@ -13448,7 +13448,7 @@        <string>String</string>        <key>Value</key>        <string>[i800,i600]</string> -    </map>   +    </map>      <key>sourceid</key>      <map>        <key>Comment</key> @@ -14669,7 +14669,7 @@        <string>Boolean</string>        <key>Value</key>        <integer>1</integer> -    </map>     +    </map>      <key>EnablePlaceProfile</key>      <map>        <key>Comment</key> @@ -15491,7 +15491,7 @@      <key>Value</key>      <integer>0</integer>    </map> -   +    <key>PathfindingLineWidth</key>    <map>      <key>Comment</key> @@ -15532,7 +15532,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 260a3d8ce4..4fb6607723 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -124,6 +124,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> @@ -131,7 +134,6 @@  #include <boost/algorithm/string.hpp>  #include <boost/regex.hpp> -  #if LL_WINDOWS  #	include <share.h> // For _SH_DENYWR in processMarkerFiles  #else @@ -1731,6 +1733,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(); @@ -2787,11 +2792,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); @@ -3375,8 +3380,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 ae33acb842..4cb1ca6cc0 100755 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -46,7 +46,6 @@  #include "message.h"  #include "llstartup.h"              // login_alert_done -  LLFloaterTOS::LLFloaterTOS(const LLSD& data)  :	LLModalDialog( data["message"].asString() ),  	mMessage(data["message"].asString()), @@ -85,7 +84,7 @@ protected:  	{  		if ( mParent )  		{ -			mParent->setSiteIsAlive( true ); +			mParent->setSiteIsAlive(true);  		}  	} @@ -136,6 +135,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. @@ -147,6 +160,7 @@ BOOL LLFloaterTOS::postBuild()  			// All links from tos_html should be opened in external browser  			media_plugin->setOverrideClickTarget("_external");  		} +#endif  	}  	return TRUE; @@ -154,6 +168,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 @@ -182,6 +203,7 @@ void LLFloaterTOS::setSiteIsAlive( bool alive )  			tos_agreement->setEnabled( true );  		}  	} +#endif  }  LLFloaterTOS::~LLFloaterTOS() diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 6aaf45c35d..984c650128 100755 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -1605,7 +1605,7 @@ bool sort_alpha(const LLViewerInventoryCategory* cat1, const LLViewerInventoryCa  void dump_trace(std::string& message, S32 depth, LLError::ELevel log_level)  { -    llinfos << "validate_marketplacelistings : error = "<< log_level << ", depth = " << depth << ", message = " << message <<  llendl; +    LL_INFOS() << "validate_marketplacelistings : error = "<< log_level << ", depth = " << depth << ", message = " << message <<  LL_ENDL;  }  // Make all relevant business logic checks on the marketplace listings starting with the folder as argument. 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 455a9951ac..0db3297550 100755 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -752,10 +752,15 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)  		LL_INFOS() << "LLToolPie handleDoubleClick (becoming mouseDown)" << LL_ENDL;  	} -	if (!mDoubleClickTimer.getStarted() || (mDoubleClickTimer.getElapsedTimeF32() > 0.3f)) +	if (handleMediaDblClick(mPick))  	{ -	    mDoubleClickTimer.stop(); -	    return FALSE; +		return TRUE; +	} +     +    	if (!mDoubleClickTimer.getStarted() || (mDoubleClickTimer.getElapsedTimeF32() > 0.3f)) +	{ +		mDoubleClickTimer.stop(); +		return FALSE;  	}  	mDoubleClickTimer.stop(); @@ -1470,56 +1475,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(); +    //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(); +    if (!parcel || +        objectp.isNull() || +        pick.mObjectFace < 0 || +        pick.mObjectFace >= objectp->getNumTEs()) +    { +        LLViewerMediaFocus::getInstance()->clearFocus(); -		return false; -	} +        return false; +    } -	// Does this face have media? -	const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); -	if(!tep) -		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()); +    LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL; +    if (!mep) +        return false; -	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. -		} +    viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); -		return true; -	} +    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(); +    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 6e9335251b..6391e675c5 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 f36d602ae5..2186ed3c52 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 3eae0f8d86..ffae3c0e1f 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" @@ -167,7 +168,7 @@ public:  		{  			LL_ERRS() << "impl already has an outstanding responder" << LL_ENDL;  		} -		 +  		mMediaImpl->mMimeTypeProbe = this;  	} @@ -189,19 +190,19 @@ private:  		std::string mime_type = media_type.substr(0, idx1);  		LL_DEBUGS() << "status is " << getStatus() << ", media type \"" << media_type << "\"" << LL_ENDL; -		 +  		// 2xx status codes indicate success.  		// Most 4xx status codes are successful enough for our purposes.  		// 499 is the error code for host not found, timeout, etc. -		// 500 means "Internal Server error" but we decided it's okay to  +		// 500 means "Internal Server error" but we decided it's okay to  		//     accept this and go past it in the MIME type probe  		// 302 means the resource can be found temporarily in a different place - added this for join.secondlife.com  		// 499 is a code specifc to join.secondlife.com apparently safe to ignore  //		if(	((status >= 200) && (status < 300))	|| -//			((status >= 400) && (status < 499))	||  +//			((status >= 400) && (status < 499))	||  //			(status == 500) ||  //			(status == 302) || -//			(status == 499)  +//			(status == 499)  //			)  		// We now no longer check the error code returned from the probe.  		// If we have a mime type, use it.  If not, default to the web plugin and let it handle error reporting. @@ -229,7 +230,7 @@ private:  		// the call to initializeMedia may disconnect the responder, which will clear mMediaImpl.  		// Make a local copy so we can call loadURI() afterwards.  		LLViewerMediaImpl *impl = mMediaImpl; -		 +  		if(impl && !mInitialized && ! mime_type.empty())  		{  			if(impl->initializeMedia(mime_type)) @@ -240,13 +241,13 @@ private:  			}  		}  	} -	 +  public:  	void cancelRequest()  	{  		disconnectOwner();  	} -	 +  private:  	void disconnectOwner()  	{ @@ -261,8 +262,8 @@ private:  		}  		mMediaImpl = NULL;  	} -	 -	 + +  public:  		LLViewerMediaImpl *mMediaImpl;  		bool mInitialized; @@ -284,13 +285,12 @@ public:  		const LLChannelDescriptors& channels,  		const LLIOPipe::buffer_ptr_t& buffer)  	{ -		// We don't care about the content of the response, only the Set-Cookie header. -		LL_DEBUGS("MediaAuth") << dumpResponse()  -				<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL; +		const std::string url = getURL(); +  		const std::string& cookie = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE); -		 +  		// *TODO: What about bad status codes?  Does this destroy previous cookies? -		LLViewerMedia::openIDCookieResponse(cookie); +		LLViewerMedia::openIDCookieResponse(url, cookie);  	}  }; @@ -313,7 +313,7 @@ public:  		const LLIOPipe::buffer_ptr_t& buffer)  	{  		// We don't care about the content of the response, only the set-cookie header. -		LL_WARNS("MediaAuth") << dumpResponse()  +		LL_WARNS("MediaAuth") << dumpResponse()  				<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;  		LLSD stripped_content = getResponseHeaders(); @@ -364,7 +364,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) @@ -391,8 +391,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)  { @@ -416,24 +416,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(); @@ -446,7 +446,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())  		{ @@ -454,7 +454,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;  			}  		} @@ -463,26 +463,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(); @@ -491,7 +491,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s  			needs_navigate = true;  		}  	} -	 +  	if(media_impl)  	{  		if(needs_navigate) @@ -510,7 +510,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;  } @@ -519,7 +519,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()) @@ -534,7 +534,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"); @@ -553,7 +553,7 @@ std::string LLViewerMedia::getCurrentUserAgent()  	codec << LLVersionInfo::getVersion();  	codec << " (" << channel << "; " << skin_name << " skin)";  	LL_INFOS() << codec.str() << LL_ENDL; -	 +  	return codec.str();  } @@ -562,7 +562,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(); @@ -651,7 +651,7 @@ void LLViewerMedia::muteListChanged()  bool LLViewerMedia::isInterestingEnough(const LLVOVolume *object, const F64 &object_interest)  {  	bool result = false; -	 +  	if (NULL == object)  	{  		result = false; @@ -667,13 +667,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;  } @@ -780,13 +780,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()) @@ -794,7 +794,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(); @@ -807,14 +807,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 @@ -824,14 +824,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"); @@ -840,19 +840,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)) @@ -883,7 +883,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; @@ -897,7 +897,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. @@ -919,11 +919,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));  					}  				} @@ -933,18 +933,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; @@ -954,7 +954,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. @@ -972,7 +972,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. @@ -984,7 +984,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg)  			}  			total_cpu += pimpl->getCPUUsage(); -		 +  			if (!pimpl->getUsedInUI() && pimpl->hasMedia())  			{  				sAnyMediaShowing = true; @@ -1008,7 +1008,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg)  			sLowestLoadableImplInterest = object->getPixelArea();  		}  	} -	 +  	if(gSavedSettings.getBOOL("MediaPerformanceManagerDebug"))  	{  		// Give impls the same ordering as the priority list @@ -1017,7 +1017,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);  	} @@ -1026,7 +1026,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg)  	{  		proximity_order[i]->mProximity = i;  	} -	 +  	LL_DEBUGS("PluginPriority") << "Total reported CPU usage is " << total_cpu << LL_ENDL;  } @@ -1045,11 +1045,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; @@ -1058,18 +1058,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()) @@ -1142,26 +1142,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 @@ -1174,7 +1174,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)) @@ -1184,26 +1184,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 @@ -1215,9 +1215,9 @@ void LLViewerMedia::clearAllCaches()  		pimpl->clearCache();  	}  } -	 +  ///////////////////////////////////////////////////////////////////////////////////////// -// static  +// static  void LLViewerMedia::setCookiesEnabled(bool enabled)  {  	// Set the "cookies enabled" flag for all loaded plugins @@ -1232,9 +1232,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 @@ -1251,7 +1251,7 @@ void LLViewerMedia::setProxyConfig(bool enable, const std::string &host, int por  }  ///////////////////////////////////////////////////////////////////////////////////////// -// static  +// static  /////////////////////////////////////////////////////////////////////////////////////////  // static  LLPluginCookieStore *LLViewerMedia::getCookieStore() @@ -1260,7 +1260,7 @@ LLPluginCookieStore *LLViewerMedia::getCookieStore()  	{  		sCookieStore = new LLPluginCookieStore;  	} -	 +  	return sCookieStore;  } @@ -1276,7 +1276,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()) @@ -1284,11 +1284,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(); @@ -1300,9 +1300,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());  } @@ -1337,23 +1337,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());  } @@ -1370,7 +1370,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);  } @@ -1388,9 +1388,34 @@ 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; +} + +  /////////////////////////////////////////////////////////////////////////////////////////  // static -void LLViewerMedia::setOpenIDCookie() +void LLViewerMedia::setOpenIDCookie(const std::string& url)  {  	if(!sOpenIDCookie.empty())  	{ @@ -1398,7 +1423,7 @@ void LLViewerMedia::setOpenIDCookie()  		// We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that.  		// We therefore do it here.  		std::string authority = sOpenIDURL.mAuthority; -		std::string::size_type host_start = authority.find('@');  +		std::string::size_type host_start = authority.find('@');  		if(host_start == std::string::npos)  		{  			// no username/password @@ -1406,20 +1431,43 @@ void LLViewerMedia::setOpenIDCookie()  		}  		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.)  			++host_start;  		} -		std::string::size_type host_end = authority.rfind(':');  +		std::string::size_type host_end = authority.rfind(':');  		if((host_end == std::string::npos) || (host_end < host_start))  		{  			// no port  			host_end = authority.size();  		} -		 +  		getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(host_start, host_end - host_start)); -		// 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(host_start, host_end - host_start); +				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  		LLSD headers = LLSD::emptyMap();  		headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";  		headers[HTTP_OUT_HEADER_COOKIE] = sOpenIDCookie; @@ -1430,7 +1478,7 @@ void LLViewerMedia::setOpenIDCookie()  		LL_DEBUGS("MediaAuth") << "Requesting " << profile_url << LL_ENDL;  		LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << LL_ENDL; -		LLHTTPClient::get(profile_url,   +		LLHTTPClient::get(profile_url,  			new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()),  			headers);  	} @@ -1442,12 +1490,12 @@ void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string  {  	LL_DEBUGS("MediaAuth") << "url = \"" << openid_url << "\", token = \"" << openid_token << "\"" << LL_ENDL; -	// 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(openid_url.c_str()); -	 +  	// We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies.  	sOpenIDCookie.clear(); @@ -1462,24 +1510,24 @@ void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string  	U8 *data = new U8[size];  	memcpy(data, openid_token.data(), size); -	LLHTTPClient::postRaw(  -		openid_url,  -		data,  -		size,  +	LLHTTPClient::postRaw( +		openid_url, +		data, +		size,  		new LLViewerMediaOpenIDResponder(),  		headers); -			 +  }  /////////////////////////////////////////////////////////////////////////////////////////  // 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);  }  ///////////////////////////////////////////////////////////////////////////////////////// @@ -1488,7 +1536,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()) @@ -1525,7 +1573,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);  	} @@ -1537,7 +1585,7 @@ LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource()  {  	LLPluginClassMedia* result = sSpareBrowserMediaSource;  	sSpareBrowserMediaSource = NULL; -	return result;  +	return result;  };  bool LLViewerMedia::hasInWorldMedia() @@ -1626,12 +1674,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), @@ -1672,7 +1720,7 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,  	mTrustedBrowser(false),  	mZoomFactor(1.0),      mCleanBrowser(false) -{  +{  	// Set up the mute list observer if it hasn't been set up already.  	if(!sViewerMediaMuteListObserverInitialized) @@ -1680,11 +1728,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); @@ -1699,7 +1747,7 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,  LLViewerMediaImpl::~LLViewerMediaImpl()  {  	destroyMediaSource(); -	 +  	LLViewerMediaTexture::removeMediaImplFromTexture(mTextureId) ;  	setTextureID(); @@ -1711,7 +1759,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()) @@ -1727,7 +1775,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. @@ -1750,7 +1798,7 @@ void LLViewerMediaImpl::createMediaSource()  		// This media shouldn't be created yet.  		return;  	} -	 +  	if(! mMediaURL.empty())  	{  		navigateInternal(); @@ -1776,15 +1824,15 @@ void LLViewerMediaImpl::destroyMediaSource()  	{  		oldImage->setPlaying(FALSE) ;  	} -	 +  	cancelMimeTypeProbe(); -	 +  	if(mMediaSource)  	{  		mMediaSource->setDeleteOK(true) ;  		delete mMediaSource;  		mMediaSource = NULL; -	}	 +	}  }  ////////////////////////////////////////////////////////////////////////////////////////// @@ -1799,11 +1847,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(); @@ -1812,7 +1860,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;  		}  	} @@ -1824,8 +1872,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 @@ -1836,8 +1888,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 @@ -1854,7 +1906,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 @@ -1868,12 +1920,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")))  			{ @@ -1886,14 +1941,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) @@ -1904,10 +1959,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; @@ -1915,7 +1970,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;  	} @@ -1926,7 +1981,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")); @@ -1935,7 +1990,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); @@ -1943,19 +1998,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, @@ -1966,7 +2021,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)  		{  			media_source->set_cookies(all_cookies);  		} -				 +  		mMediaSource = media_source;  		mMediaSource->setDeleteOK(false) ;  		updateVolume(); @@ -2009,16 +2064,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. @@ -2071,11 +2126,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();  } @@ -2176,10 +2231,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"))  			{ @@ -2218,7 +2273,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 @@ -2246,7 +2301,7 @@ std::string LLViewerMediaImpl::getCurrentMediaURL()  	{  		return mCurrentMediaURL;  	} -	 +  	return mMediaURL;  } @@ -2314,17 +2369,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; @@ -2352,7 +2407,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); @@ -2363,7 +2418,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); @@ -2371,6 +2426,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)  { @@ -2405,18 +2471,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;  }  ////////////////////////////////////////////////////////////////////////////////////////// @@ -2492,14 +2558,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;  };  ////////////////////////////////////////////////////////////////////////////////////////// @@ -2555,21 +2621,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; @@ -2585,7 +2651,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;  	} @@ -2609,13 +2675,13 @@ void LLViewerMediaImpl::navigateInternal()  		mNavigateSuspendedDeferred = true;  		return;  	} -	 +  	if(mMimeTypeProbe != NULL)  	{  		LL_WARNS() << "MIME type probe already in progress -- bailing out." << LL_ENDL;  		return;  	} -	 +  	if(mNavigateServerRequest)  	{  		setNavState(MEDIANAVSTATE_SERVER_SENT); @@ -2624,12 +2690,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); @@ -2698,27 +2764,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) +		{ +			result = true; +		} + +		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) +		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); -			// 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;  } @@ -2726,7 +2812,7 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask)  bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char)  {  	bool result = false; -	 +  	if (mMediaSource)  	{  		// only accept 'printable' characters, sigh... @@ -2734,11 +2820,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;  } @@ -2817,15 +2903,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); @@ -2834,7 +2920,7 @@ void LLViewerMediaImpl::update()  	{  		return;  	} -	 +  	if(mMediaSource->isPluginExited())  	{  		resetPreviousMediaState(); @@ -2846,18 +2932,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); @@ -2868,7 +2954,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)  			{ @@ -2881,21 +2967,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();  		}  	} @@ -2916,10 +3002,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()) @@ -2933,7 +3019,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? @@ -2959,13 +3045,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;  } @@ -2980,14 +3066,14 @@ LLUUID LLViewerMediaImpl::getMediaTextureID() const  void LLViewerMediaImpl::setVisible(bool visible)  {  	mVisible = visible; -	 +  	if(mVisible)  	{  		if(mMediaSource && mMediaSource->isPluginExited())  		{  			destroyMediaSource();  		} -		 +  		if(!mMediaSource)  		{  			createMediaSource(); @@ -3021,12 +3107,12 @@ void LLViewerMediaImpl::scaleMouse(S32 *mouse_x, S32 *mouse_y)  bool LLViewerMediaImpl::isMediaTimeBased()  {  	bool result = false; -	 +  	if(mMediaSource)  	{  		result = mMediaSource->pluginSupportsMediaTime();  	} -	 +  	return result;  } @@ -3034,14 +3120,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;  }  ////////////////////////////////////////////////////////////////////////////////////////// @@ -3054,7 +3140,7 @@ bool LLViewerMediaImpl::isMediaPaused()  		if(mMediaSource->getStatus() == MEDIA_PAUSED)  			result = true;  	} -	 +  	return result;  } @@ -3082,7 +3168,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. @@ -3108,13 +3194,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;  } @@ -3127,19 +3213,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;  } @@ -3151,7 +3237,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); @@ -3170,7 +3256,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); @@ -3192,13 +3278,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") @@ -3214,6 +3300,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; @@ -3259,7 +3352,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; @@ -3296,15 +3389,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; @@ -3460,7 +3553,7 @@ void LLViewerMediaImpl::calculateInterest()  {  	LL_RECORD_BLOCK_TIME(FTM_MEDIA_CALCULATE_INTEREST);  	LLViewerMediaTexture* texture = LLViewerTextureManager::findMediaTexture( mTextureId ); -	 +  	if(texture != NULL)  	{  		mInterest = texture->getMaxVirtualSize(); @@ -3470,7 +3563,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; @@ -3480,7 +3573,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())  		{ @@ -3493,12 +3586,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)  		{ @@ -3525,7 +3618,7 @@ void LLViewerMediaImpl::calculateInterest()  				}  			}  		} -		 +  		mNeedsMuteCheck = false;  	}  } @@ -3533,7 +3626,7 @@ void LLViewerMediaImpl::calculateInterest()  F64 LLViewerMediaImpl::getApproximateTextureInterest()  {  	F64 result = 0.0f; -	 +  	if(mMediaSource)  	{  		result = mMediaSource->getFullWidth(); @@ -3551,8 +3644,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)) @@ -3572,7 +3665,7 @@ void LLViewerMediaImpl::setUsedInUI(bool used_in_ui)  void LLViewerMediaImpl::setBackgroundColor(LLColor4 color)  { -	mBackgroundColor = color;  +	mBackgroundColor = color;  	if(mMediaSource)  	{ @@ -3583,12 +3676,12 @@ void LLViewerMediaImpl::setBackgroundColor(LLColor4 color)  F64 LLViewerMediaImpl::getCPUUsage() const  {  	F64 result = 0.0f; -	 +  	if(mMediaSource)  	{  		result = mMediaSource->getCPUUsage();  	} -	 +  	return result;  } @@ -3602,19 +3695,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();  		}  	} @@ -3623,7 +3716,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().  } @@ -3638,8 +3731,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; @@ -3678,7 +3771,7 @@ void LLViewerMediaImpl::cancelMimeTypeProbe()  		// There doesn't seem to be a way to actually cancel an outstanding request.  		// Simulate it by telling the LLMimeDiscoveryResponder not to write back any results.  		mMimeTypeProbe->cancelRequest(); -		 +  		// The above should already have set mMimeTypeProbe to NULL.  		if(mMimeTypeProbe != NULL)  		{ @@ -3687,7 +3780,7 @@ void LLViewerMediaImpl::cancelMimeTypeProbe()  	}  } -void LLViewerMediaImpl::addObject(LLVOVolume* obj)  +void LLViewerMediaImpl::addObject(LLVOVolume* obj)  {  	std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;  	for(; iter != mObjectList.end() ; ++iter) @@ -3701,14 +3794,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 ;  } @@ -3716,13 +3809,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;  } @@ -3735,12 +3828,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;  	}  } @@ -3749,7 +3842,7 @@ void LLViewerMediaImpl::setTextureID(LLUUID id)  //  bool LLViewerMediaImpl::isAutoPlayable() const  { -	return (mMediaAutoPlay &&  +	return (mMediaAutoPlay &&  			gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&  			gSavedSettings.getBOOL("MediaTentativeAutoPlay"));  } @@ -3760,20 +3853,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)  	{ @@ -3786,7 +3879,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); @@ -3799,7 +3892,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++) @@ -3843,7 +3936,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 1ce42e97b8..ede408dd0c 100755 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -150,7 +150,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); @@ -163,7 +163,8 @@ public:  	static LLSD getHeaders();  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 LLPluginCookieStore *sCookieStore; @@ -225,7 +226,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(); @@ -238,6 +240,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 37b249dddd..fc275eb2f0 100755 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -590,7 +590,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 0e30c79796..f96c4b7bf0 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 52f51d4c97..d34e76f6f6 100755 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -316,6 +316,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 3f557d0d0f..8de9a1a99a 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1438,7 +1438,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"> @@ -3191,7 +3191,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 70ba4d5077..b4c5cba1fd 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 6f57daf151..7cb4aeb121 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 -  | 
