diff options
Diffstat (limited to 'indra')
63 files changed, 1435 insertions, 8318 deletions
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 7a320ffc59..1a3b6c5117 100755 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -191,7 +191,7 @@ if (DARWIN) add_definitions(-DLL_DARWIN=1) set(CMAKE_CXX_LINK_FLAGS "-Wl,-no_compact_unwind -Wl,-headerpad_max_install_names,-search_paths_first") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}") - set(DARWIN_extra_cstar_flags "-g") + set(DARWIN_extra_cstar_flags "-g -Wno-unused-local-typedef -Wno-deprecated-declarations") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DARWIN_extra_cstar_flags}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DARWIN_extra_cstar_flags}") # NOTE: it's critical that the optimization flag is put in front. 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 76d92d7a48..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) @@ -130,10 +130,10 @@ endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(DARWIN 1) - # now we only support Xcode 6.0 using 10.9 (Mavericks), minimum OS 10.7 (Lion) - set(XCODE_VERSION 6.0) + # now we only support Xcode 7.0 using 10.11 (El Capitan), minimum OS 10.7 (Lion) + set(XCODE_VERSION 7.0) set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) - set(CMAKE_OSX_SYSROOT macosx10.9) + set(CMAKE_OSX_SYSROOT macosx10.11) set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvm.clang.1_0") set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL 3) 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/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp index 715df36f39..e0aa30cc1a 100755 --- a/indra/llcommon/llprocess.cpp +++ b/indra/llcommon/llprocess.cpp @@ -738,8 +738,11 @@ LLProcess::LLProcess(const LLSDOrParams& params): { mPipes.replace(i, new ReadPipeImpl(desc, pipe, FILESLOT(i))); } - LL_DEBUGS("LLProcess") << "Instantiating " << typeid(mPipes[i]).name() - << "('" << desc << "')" << LL_ENDL; + // Removed temporaily for Xcode 7 build tests: error was: + // "error: expression with side effects will be evaluated despite + // being used as an operand to 'typeid' [-Werror,-Wpotentially-evaluated-expression]"" + //LL_DEBUGS("LLProcess") << "Instantiating " << typeid(mPipes[i]).name() + // << "('" << desc << "')" << LL_ENDL; } } 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..14d4a14deb 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& Responder::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..fd04fc4b62 100755 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -146,7 +146,7 @@ void LLPluginClassMedia::reset() mClickTarget.clear(); mClickUUID.clear(); mStatusCode = 0; - + mClickEnforceTarget = false; // media_time class @@ -670,6 +670,19 @@ bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD return true; } +void LLPluginClassMedia::setCookie(std::string uri, std::string name, std::string value, std::string domain, std::string path)
+{
+ 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);
+
+ sendMessage(message);
+}
+ void LLPluginClassMedia::loadURI(const std::string &uri) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri"); diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 96d577f43c..255fb0e2f1 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); + void loadURI(const std::string &uri); // "Loading" means uninitialized or any state prior to fully running (processing commands) 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..fb811452be 100755 --- a/indra/llui/llfocusmgr.cpp +++ b/indra/llui/llfocusmgr.cpp @@ -47,6 +47,12 @@ 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; diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h index afd2a8ce06..950ac55325 100755 --- a/indra/llui/llfocusmgr.h +++ b/indra/llui/llfocusmgr.h @@ -57,6 +57,7 @@ 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); virtual void onTopLost(); // called when registered as top ctrl and user clicks elsewhere 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/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 1c9160a42d..deb8cb90d8 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -239,7 +239,11 @@ attributedStringInfo getSegments(NSAttributedString *str) { [glContext setValues:(const GLint*)1 forParameter:NSOpenGLCPSwapInterval]; } else { - [glContext setValues:(const GLint*)0 forParameter:NSOpenGLCPSwapInterval]; + // supress this error after move to Xcode 7: + // error: null passed to a callee that requires a non-null argument [-Werror,-Wnonnull] + // Tried using ObjC 'nonnull' keyword as per SO article but didn't build + GLint swapInterval=0; + [glContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; } mOldResize = false; 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..376bef3e50 100755 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -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..16015be672 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 /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..7f538e16d8 --- /dev/null +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -0,0 +1,817 @@ +/** +* @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 width, int height); + 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 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 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() +{ + mLLCEFLib->reset(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +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 width, int height) +{ + if (mPixels && pixels) + { + 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::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::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 << "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 = "CEF plugin 1.0.0"; + 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") + { + } + 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 + { + //std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; + } + + 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) + { + if (message_name == "init") + { + // event callbacks from LLCefLib + mLLCEFLib->setOnPageChangedCallback(boost::bind(&MediaPluginCEF::onPageChangedCallback, this, _1, _2, _3)); + 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->setOnCursorChangedCallback(boost::bind(&MediaPluginCEF::onCursorChangedCallback, this, _1, _2)); + + 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 = 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 = message_in.getValue("path"); // n.b. always has trailing platform-specific dir-delimiter + mCachePath = user_data_path + "cef_cache"; + mCookiePath = user_data_path + "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");
+ mLLCEFLib->setCookie(uri, name, value, domain, path);
+ } + 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"); + + //std::string modifiers = message_in.getValue("modifiers"); + + S32 button = message_in.getValueS32("button"); + LLCEFLib::EMouseButton btn = LLCEFLib::MB_MOUSE_BUTTON_LEFT; + if (button == 0) btn = LLCEFLib::MB_MOUSE_BUTTON_LEFT; + if (button == 1) btn = LLCEFLib::MB_MOUSE_BUTTON_RIGHT; + if (button == 2) btn = LLCEFLib::MB_MOUSE_BUTTON_MIDDLE; + + if (event == "down") + { + 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") + { + 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") + { + // TODO: do we need this ? + } + else + { + mLLCEFLib->mouseMove(x, y); + } + } + else if (message_name == "scroll_event") + { + S32 y = message_in.getValueS32("y"); + const int scaling_factor = 40; + y *= -scaling_factor; + + mLLCEFLib->mouseWheel(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"); + 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); + } + +#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 == "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 + { + //std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; + }; + } +} + +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, LLSD native_key_data = LLSD::emptyMap()) +{ +#if LL_DARWIN + std::string utf8_text; + + if (key < 128) + { + utf8_text = (char)key; + } + + switch ((KEY)key) + { + case KEY_BACKSPACE: utf8_text = (char)8; break; + case KEY_TAB: utf8_text = (char)9; break; + case KEY_RETURN: utf8_text = (char)13; break; + case KEY_PAD_RETURN: utf8_text = (char)13; break; + case KEY_ESCAPE: utf8_text = (char)27; break; + + default: + break; + } + + 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); + + mLLCEFLib->keyboardEvent(key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); +#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); +#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/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 16877c345e..73ed651e65 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} @@ -1764,44 +1760,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 ) @@ -1846,10 +1810,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) @@ -2016,9 +1980,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 ) @@ -2130,7 +2093,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) @@ -2185,20 +2148,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 2e14a9557d..fcdb2e109f 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -3.8.6 +4.0.0 diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index fbf2a04bcc..9e80e26e3f 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 @@ -2788,7 +2790,7 @@ bool LLAppViewer::initConfiguration() #endif if (!gArgs.empty()) { - gWindowTitle += std::string(" ") + gArgs; + gWindowTitle += std::string(" ") + gArgs; } LLStringUtil::truncate(gWindowTitle, 255); @@ -3372,8 +3374,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/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 73faed7ef5..d999c6f52b 100755 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -428,6 +428,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 +1006,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; }; diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 988733b85a..cb3a864d63 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); diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index ada829eb4b..1ab672aafc 100755 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -729,7 +729,10 @@ BOOL LLViewerKeyboard::handleKey(KEY translated_key, MASK translated_mask, BOOL return mKeyHandledByUI[translated_key]; } - +BOOL LLViewerKeyboard::handleKeyUp(KEY translated_key, MASK translated_mask) +{ + return gViewerWindow->handleKeyUp(translated_key, translated_mask); +} BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name) { diff --git a/indra/newview/llviewerkeyboard.h b/indra/newview/llviewerkeyboard.h index ca73212ed1..110dc89d28 100755 --- a/indra/newview/llviewerkeyboard.h +++ b/indra/newview/llviewerkeyboard.h @@ -89,6 +89,7 @@ public: LLViewerKeyboard(); BOOL handleKey(KEY key, MASK mask, BOOL repeated); + BOOL handleKeyUp(KEY key, MASK mask); S32 loadBindings(const std::string& filename); // returns number bound, 0 on error S32 loadBindingsXML(const std::string& filename); // returns number bound, 0 on error diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 3eae0f8d86..1098b2a7e1 100755 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -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" @@ -284,13 +285,16 @@ public: const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { + const std::string url = getURL(); + llinfos << "@@@ URL to set cookie on" << url << llendl; + // We don't care about the content of the response, only the Set-Cookie header. - LL_DEBUGS("MediaAuth") << dumpResponse() - << " [headers:" << getResponseHeaders() << "]" << LL_ENDL; + llinfos << dumpResponse() + << " [headers:" << getResponseHeaders() << "]" << llendl; 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); } }; @@ -1199,7 +1203,7 @@ void LLViewerMedia::clearAllCookies() } // If we have an OpenID cookie, re-add it to the cookie store. - setOpenIDCookie(); + setOpenIDCookie(std::string()); } ///////////////////////////////////////////////////////////////////////////////////////// @@ -1302,7 +1306,7 @@ void LLViewerMedia::loadCookieFile() } // If we have an OpenID cookie, re-add it to the cookie store. - setOpenIDCookie(); + setOpenIDCookie(std::string()); } @@ -1388,9 +1392,31 @@ LLSD LLViewerMedia::getHeaders() return headers; } + /////////////////////////////////////////////////////////////////////////////////////////
+ // static
+bool LLViewerMedia::parseRawCookie(const std::string raw_cookie, std::string& name, std::string& value, std::string& path)
+{
+ 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
+
+ return true;
+ }
+ }
+
+ return false;
+}
+ + ///////////////////////////////////////////////////////////////////////////////////////// // static -void LLViewerMedia::setOpenIDCookie() +void LLViewerMedia::setOpenIDCookie(const std::string& url) { if(!sOpenIDCookie.empty()) { @@ -1419,6 +1445,26 @@ void LLViewerMedia::setOpenIDCookie() getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(host_start, host_end - host_start)); + 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 = "";
+ if (parseRawCookie(sOpenIDCookie, cookie_name, cookie_value, cookie_path))
+ {
+ media_instance->getMediaPlugin()->setCookie(url, cookie_name, cookie_value, cookie_host, cookie_path);
+ }
+ }
+ }
+
+ // 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] = "*/*"; @@ -1473,13 +1519,13 @@ void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string ///////////////////////////////////////////////////////////////////////////////////////// // 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); } ///////////////////////////////////////////////////////////////////////////////////////// @@ -1803,7 +1849,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ // 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(); @@ -1872,6 +1918,9 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ 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(); @@ -2698,27 +2747,48 @@ void LLViewerMediaImpl::navigateStop() bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) { bool result = false; - + if (mMediaSource) { // FIXME: THIS IS SO WRONG. // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... - if( MASK_CONTROL & mask && key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END) + if (MASK_CONTROL & mask && key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END) { result = true; } - - if(!result) + + if (!result) { - + LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData(); - - result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask, native_key_data); - // 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_DOWN, key, mask, native_key_data); } } - + + return result; +} + +////////////////////////////////////////////////////////////////////////////////////////// +bool LLViewerMediaImpl::handleKeyUpHere(KEY key, MASK mask) +{ + bool result = false; + + if (mMediaSource) + { + // FIXME: THIS IS SO WRONG. + // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... + if (MASK_CONTROL & mask && key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END) + { + result = true; + } + + if (!result) + { + LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData(); + result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_UP, key, mask, native_key_data); + } + } + return result; } diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 1ce42e97b8..4ee1b56a2a 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); + static void setOpenIDCookie(const std::string& url); static void onTeleportFinished(); static LLPluginCookieStore *sCookieStore; @@ -238,6 +239,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..1265ca0a70 100755 --- a/indra/newview/llviewermediafocus.cpp +++ b/indra/newview/llviewermediafocus.cpp @@ -352,6 +352,13 @@ BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent) return true; } +BOOL LLViewerMediaFocus::handleKeyUp(KEY key, MASK mask, BOOL called_from_parent) +{ + return true; +} + + + BOOL LLViewerMediaFocus::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) { LLViewerMediaImpl* media_impl = getFocusedMediaImpl(); diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h index f03dd8751e..42c841df15 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); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index ba84d7aa2c..b6212e0958 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1399,10 +1399,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); @@ -2545,6 +2544,41 @@ void LLViewerWindow::draw() } // Takes a single keydown event, usually when UI is visible +BOOL LLViewerWindow::handleKeyUp(KEY key, MASK mask) +{ + if (gFocusMgr.getKeyboardFocus() + && !(mask & (MASK_CONTROL | MASK_ALT)) + && !gFocusMgr.getKeystrokesOnly()) + { + // We have keyboard focus, and it's not an accelerator + 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); + } + } + + LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); + 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 diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 7fde52d4e1..17e9ac2636 100755 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -314,6 +314,7 @@ public: LLView* getHintHolder() { return mHintHolder.get(); } LLView* getLoginPanelHolder() { return mLoginPanelHolder.get(); } BOOL handleKey(KEY key, MASK mask); + BOOL handleKeyUp(KEY key, MASK mask); void handleScrollWheel (S32 clicks); // add and remove views from "popup" layer diff --git a/indra/newview/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/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/viewer_manifest.py b/indra/newview/viewer_manifest.py index cae6bded9f..9a65171d44 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,115 @@ 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() + # 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 +800,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 +819,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 +879,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 +1055,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 +1075,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 +1216,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 - |