diff options
Diffstat (limited to 'indra')
-rw-r--r-- | indra/cmake/Copy3rdPartyLibs.cmake | 13 | ||||
-rw-r--r-- | indra/llcommon/llprocess.cpp | 12 | ||||
-rw-r--r-- | indra/llcommon/llprocess.h | 29 | ||||
-rw-r--r-- | indra/llcommon/tests/llprocess_test.cpp | 89 | ||||
-rw-r--r-- | indra/llplugin/llpluginmessagepipe.cpp | 4 | ||||
-rw-r--r-- | indra/llplugin/llpluginprocesschild.cpp | 457 | ||||
-rw-r--r-- | indra/llplugin/slplugin/slplugin.cpp | 29 | ||||
-rw-r--r-- | indra/llwindow/llwindowwin32.cpp | 2 | ||||
-rw-r--r-- | indra/llwindow/llwindowwin32.h | 2 | ||||
-rw-r--r-- | indra/media_plugins/CMakeLists.txt | 3 | ||||
-rw-r--r-- | indra/media_plugins/cef/media_plugin_cef.cpp | 77 | ||||
-rw-r--r-- | indra/media_plugins/example/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/media_plugins/example/media_plugin_example.cpp | 707 | ||||
-rw-r--r-- | indra/newview/CMakeLists.txt | 1 | ||||
-rw-r--r-- | indra/newview/installers/windows/installer_template.nsi | 31 | ||||
-rw-r--r-- | indra/newview/llviewermedia.cpp | 4 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/mime_types.xml | 35 | ||||
-rwxr-xr-x | indra/newview/viewer_manifest.py | 8 |
18 files changed, 781 insertions, 724 deletions
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 14510d654f..c7fb7a5301 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -102,12 +102,17 @@ if(WINDOWS) unset(debug_msvc_redist_path CACHE) endif() + if(ADDRESS_SIZE EQUAL 32) + # this folder contains the 32bit DLLs.. (yes really!) + set(registry_find_path "[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/SysWOW64") + else(ADDRESS_SIZE EQUAL 32) + # this folder contains the 64bit DLLs.. (yes really!) + set(registry_find_path "[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/System32") + endif(ADDRESS_SIZE EQUAL 32) + FIND_PATH(release_msvc_redist_path NAME msvcr${MSVC_VER}.dll PATHS - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\${MSVC_VERDOT}\\Setup\\VC;ProductDir]/redist/x86/Microsoft.VC${MSVC_VER}.CRT - [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/SysWOW64 - [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/System32 - ${MSVC_REDIST_PATH} + ${registry_find_path} NO_DEFAULT_PATH ) diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp index 8c321d06b9..5753efdc59 100644 --- a/indra/llcommon/llprocess.cpp +++ b/indra/llcommon/llprocess.cpp @@ -517,6 +517,10 @@ LLProcessPtr LLProcess::create(const LLSDOrParams& params) LLProcess::LLProcess(const LLSDOrParams& params): mAutokill(params.autokill), + // Because 'autokill' originally meant both 'autokill' and 'attached', to + // preserve existing semantics, we promise that mAttached defaults to the + // same setting as mAutokill. + mAttached(params.attached.isProvided()? params.attached : params.autokill), mPipes(NSLOTS) { // Hmm, when you construct a ptr_vector with a size, it merely reserves @@ -625,9 +629,9 @@ LLProcess::LLProcess(const LLSDOrParams& params): // std handles and the like, and that's a bit more detachment than we // want. autokill=false just means not to implicitly kill the child when // the parent terminates! -// chkapr(apr_procattr_detach_set(procattr, params.autokill? 0 : 1)); +// chkapr(apr_procattr_detach_set(procattr, mAutokill? 0 : 1)); - if (params.autokill) + if (mAutokill) { #if ! defined(APR_HAS_PROCATTR_AUTOKILL_SET) // Our special preprocessor symbol isn't even defined -- wrong APR @@ -696,7 +700,7 @@ LLProcess::LLProcess(const LLSDOrParams& params): // take steps to terminate the child. This is all suspenders-and-belt: in // theory our destructor should kill an autokill child, but in practice // that doesn't always work (e.g. VWR-21538). - if (params.autokill) + if (mAutokill) { /*==========================================================================*| // NO: There may be an APR bug, not sure -- but at least on Mac, when @@ -799,7 +803,7 @@ LLProcess::~LLProcess() sProcessListener.dropPoll(*this); } - if (mAutokill) + if (mAttached) { kill("destructor"); } diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h index bfac4567a5..e3386ad88e 100644 --- a/indra/llcommon/llprocess.h +++ b/indra/llcommon/llprocess.h @@ -167,6 +167,7 @@ public: args("args"), cwd("cwd"), autokill("autokill", true), + attached("attached", true), files("files"), postend("postend"), desc("desc") @@ -183,9 +184,31 @@ public: Multiple<std::string> args; /// current working directory, if need it changed Optional<std::string> cwd; - /// implicitly kill process on destruction of LLProcess object - /// (default true) + /// implicitly kill child process on termination of parent, whether + /// voluntary or crash (default true) Optional<bool> autokill; + /// implicitly kill process on destruction of LLProcess object + /// (default same as autokill) + /// + /// Originally, 'autokill' conflated two concepts: kill child process on + /// - destruction of its LLProcess object, and + /// - termination of parent process, voluntary or otherwise. + /// + /// It's useful to tease these apart. Some child processes are sent a + /// "clean up and terminate" message before the associated LLProcess + /// object is destroyed. A child process launched with attached=false + /// has an extra time window from the destruction of its LLProcess + /// until parent-process termination in which to perform its own + /// orderly shutdown, yet autokill=true still guarantees that we won't + /// accumulate orphan instances of such processes indefinitely. With + /// attached=true, if a child process cannot clean up between the + /// shutdown message and LLProcess destruction (presumably very soon + /// thereafter), it's forcibly killed anyway -- which can lead to + /// distressing user-visible crash indications. + /// + /// (The usefulness of attached=true with autokill=false is less + /// clear, but we don't prohibit that combination.) + Optional<bool> attached; /** * Up to three FileParam items: for child stdin, stdout, stderr. * Passing two FileParam entries means default treatment for stderr, @@ -540,7 +563,7 @@ private: std::string mDesc; std::string mPostend; apr_proc_t mProcess; - bool mAutokill; + bool mAutokill, mAttached; Status mStatus; // explicitly want this ptr_vector to be able to store NULLs typedef boost::ptr_vector< boost::nullable<BasePipe> > PipeVector; diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp index 5ba343b183..b27e125d2e 100644 --- a/indra/llcommon/tests/llprocess_test.cpp +++ b/indra/llcommon/tests/llprocess_test.cpp @@ -789,6 +789,69 @@ namespace tut template<> template<> void object::test<10>() { + set_test_name("attached=false"); + // almost just like autokill=false, except set autokill=true with + // attached=false. + NamedTempFile from("from", "not started"); + NamedTempFile to("to", ""); + LLProcess::handle phandle(0); + { + PythonProcessLauncher py(get_test_name(), + "from __future__ import with_statement\n" + "import sys, time\n" + "with open(sys.argv[1], 'w') as f:\n" + " f.write('ok')\n" + "# wait for 'go' from test program\n" + "for i in xrange(60):\n" + " time.sleep(1)\n" + " with open(sys.argv[2]) as f:\n" + " go = f.read()\n" + " if go == 'go':\n" + " break\n" + "else:\n" + " with open(sys.argv[1], 'w') as f:\n" + " f.write('never saw go')\n" + " sys.exit(1)\n" + "# okay, saw 'go', write 'ack'\n" + "with open(sys.argv[1], 'w') as f:\n" + " f.write('ack')\n"); + py.mParams.args.add(from.getName()); + py.mParams.args.add(to.getName()); + py.mParams.autokill = true; + py.mParams.attached = false; + py.launch(); + // Capture handle for later + phandle = py.mPy->getProcessHandle(); + // Wait for the script to wake up and do its first write + int i = 0, timeout = 60; + for ( ; i < timeout; ++i) + { + yield(); + if (readfile(from.getName(), "from autokill script") == "ok") + break; + } + // If we broke this loop because of the counter, something's wrong + ensure("script never started", i < timeout); + // Now destroy the LLProcess, which should NOT kill the child! + } + // If the destructor killed the child anyway, give it time to die + yield(2); + // How do we know it's not terminated? By making it respond to + // a specific stimulus in a specific way. + { + std::ofstream outf(to.getName().c_str()); + outf << "go"; + } // flush and close. + // now wait for the script to terminate... one way or another. + waitfor(phandle, "autokill script"); + // If the LLProcess destructor implicitly called kill(), the + // script could not have written 'ack' as we expect. + ensure_equals(get_test_name() + " script output", readfile(from.getName()), "ack"); + } + + template<> template<> + void object::test<11>() + { set_test_name("'bogus' test"); CaptureLog recorder; PythonProcessLauncher py(get_test_name(), @@ -801,7 +864,7 @@ namespace tut } template<> template<> - void object::test<11>() + void object::test<12>() { set_test_name("'file' test"); // Replace this test with one or more real 'file' tests when we @@ -815,7 +878,7 @@ namespace tut } template<> template<> - void object::test<12>() + void object::test<13>() { set_test_name("'tpipe' test"); // Replace this test with one or more real 'tpipe' tests when we @@ -832,7 +895,7 @@ namespace tut } template<> template<> - void object::test<13>() + void object::test<14>() { set_test_name("'npipe' test"); // Replace this test with one or more real 'npipe' tests when we @@ -850,7 +913,7 @@ namespace tut } template<> template<> - void object::test<14>() + void object::test<15>() { set_test_name("internal pipe name warning"); CaptureLog recorder; @@ -914,7 +977,7 @@ namespace tut } while (0) template<> template<> - void object::test<15>() + void object::test<16>() { set_test_name("get*Pipe() validation"); PythonProcessLauncher py(get_test_name(), @@ -934,7 +997,7 @@ namespace tut } template<> template<> - void object::test<16>() + void object::test<17>() { set_test_name("talk to stdin/stdout"); PythonProcessLauncher py(get_test_name(), @@ -992,7 +1055,7 @@ namespace tut } template<> template<> - void object::test<17>() + void object::test<18>() { set_test_name("listen for ReadPipe events"); PythonProcessLauncher py(get_test_name(), @@ -1052,7 +1115,7 @@ namespace tut } template<> template<> - void object::test<18>() + void object::test<19>() { set_test_name("ReadPipe \"eof\" event"); PythonProcessLauncher py(get_test_name(), @@ -1078,7 +1141,7 @@ namespace tut } template<> template<> - void object::test<19>() + void object::test<20>() { set_test_name("setLimit()"); PythonProcessLauncher py(get_test_name(), @@ -1107,7 +1170,7 @@ namespace tut } template<> template<> - void object::test<20>() + void object::test<21>() { set_test_name("peek() ReadPipe data"); PythonProcessLauncher py(get_test_name(), @@ -1160,7 +1223,7 @@ namespace tut } template<> template<> - void object::test<21>() + void object::test<22>() { set_test_name("bad postend"); std::string pumpname("postend"); @@ -1185,7 +1248,7 @@ namespace tut } template<> template<> - void object::test<22>() + void object::test<23>() { set_test_name("good postend"); PythonProcessLauncher py(get_test_name(), @@ -1241,7 +1304,7 @@ namespace tut }; template<> template<> - void object::test<23>() + void object::test<24>() { set_test_name("all data visible at postend"); PythonProcessLauncher py(get_test_name(), diff --git a/indra/llplugin/llpluginmessagepipe.cpp b/indra/llplugin/llpluginmessagepipe.cpp index 7e2bf90ad1..9468696507 100644 --- a/indra/llplugin/llpluginmessagepipe.cpp +++ b/indra/llplugin/llpluginmessagepipe.cpp @@ -215,7 +215,7 @@ bool LLPluginMessagePipe::pumpOutput() else if(APR_STATUS_IS_EOF(status)) { // This is what we normally expect when a plugin exits. - LL_INFOS() << "Got EOF from plugin socket. " << LL_ENDL; + //LL_INFOS() << "Got EOF from plugin socket. " << LL_ENDL; if(mOwner) { @@ -329,7 +329,7 @@ bool LLPluginMessagePipe::pumpInput(F64 timeout) else if(APR_STATUS_IS_EOF(status)) { // This is what we normally expect when a plugin exits. - LL_INFOS("PluginSocket") << "Got EOF from plugin socket. " << LL_ENDL; + //LL_INFOS("PluginSocket") << "Got EOF from plugin socket. " << LL_ENDL; if(mOwner) { diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp index be80d38305..e24d222cb6 100644 --- a/indra/llplugin/llpluginprocesschild.cpp +++ b/indra/llplugin/llpluginprocesschild.cpp @@ -1,30 +1,30 @@ -/** - * @file llpluginprocesschild.cpp - * @brief LLPluginProcessChild handles the child side of the external-process plugin API. - * - * @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 - */ +/** +* @file llpluginprocesschild.cpp +* @brief LLPluginProcessChild handles the child side of the external-process plugin API. +* +* @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" @@ -50,7 +50,7 @@ LLPluginProcessChild::LLPluginProcessChild() LLPluginProcessChild::~LLPluginProcessChild() { - if(mInstance != NULL) + if (mInstance != NULL) { sendMessageToPlugin(LLPluginMessage("base", "cleanup")); @@ -58,7 +58,7 @@ LLPluginProcessChild::~LLPluginProcessChild() // appears to fail and lock up which means that a given instance of the slplugin process never exits. // This is bad, especially when users try to update their version of SL - it fails because the slplugin // process as well as a bunch of plugin specific files are locked and cannot be overwritten. - exit( 0 ); + exit(0); //delete mInstance; //mInstance = NULL; } @@ -81,166 +81,173 @@ void LLPluginProcessChild::idle(void) bool idle_again; do { - if(APR_STATUS_IS_EOF(mSocketError)) - { - // Plugin socket was closed. This covers both normal plugin termination and host crashes. - setState(STATE_ERROR); - } - else if(mSocketError != APR_SUCCESS) - { - LL_INFOS("Plugin") << "message pipe is in error state (" << mSocketError << "), moving to STATE_ERROR"<< LL_ENDL; - setState(STATE_ERROR); - } + if (mState < STATE_SHUTDOWNREQ) + { // Once we have hit the shutdown request state checking for errors might put us in a spurious + // error state... don't do that. - if((mState > STATE_INITIALIZED) && (mMessagePipe == NULL)) - { - // The pipe has been closed -- we're done. - // TODO: This could be slightly more subtle, but I'm not sure it needs to be. - LL_INFOS("Plugin") << "message pipe went away, moving to STATE_ERROR"<< LL_ENDL; - setState(STATE_ERROR); + if (APR_STATUS_IS_EOF(mSocketError)) + { + // Plugin socket was closed. This covers both normal plugin termination and host crashes. + setState(STATE_ERROR); + } + else if (mSocketError != APR_SUCCESS) + { + LL_INFOS("Plugin") << "message pipe is in error state (" << mSocketError << "), moving to STATE_ERROR" << LL_ENDL; + setState(STATE_ERROR); + } + + if ((mState > STATE_INITIALIZED) && (mMessagePipe == NULL)) + { + // The pipe has been closed -- we're done. + // TODO: This could be slightly more subtle, but I'm not sure it needs to be. + LL_INFOS("Plugin") << "message pipe went away, moving to STATE_ERROR" << LL_ENDL; + setState(STATE_ERROR); + } } - + // If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState(). // USE THIS CAREFULLY, since it can starve other code. Specifically make sure there's no way to get into a closed cycle and never return. // When in doubt, don't do it. idle_again = false; - - if(mInstance != NULL) + + if (mInstance != NULL) { // Provide some time to the plugin mInstance->idle(); } - - switch(mState) + + switch (mState) { - case STATE_UNINITIALIZED: + case STATE_UNINITIALIZED: break; - case STATE_INITIALIZED: - if(mSocket->blockingConnect(mLauncherHost)) + case STATE_INITIALIZED: + if (mSocket->blockingConnect(mLauncherHost)) + { + // This automatically sets mMessagePipe + new LLPluginMessagePipe(this, mSocket); + + setState(STATE_CONNECTED); + } + else + { + // connect failed + setState(STATE_ERROR); + } + break; + + case STATE_CONNECTED: + sendMessageToParent(LLPluginMessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hello")); + setState(STATE_PLUGIN_LOADING); + break; + + case STATE_PLUGIN_LOADING: + if (!mPluginFile.empty()) + { + mInstance = new LLPluginInstance(this); + if (mInstance->load(mPluginDir, mPluginFile) == 0) { - // This automatically sets mMessagePipe - new LLPluginMessagePipe(this, mSocket); - - setState(STATE_CONNECTED); + mHeartbeat.start(); + mHeartbeat.setTimerExpirySec(HEARTBEAT_SECONDS); + mCPUElapsed = 0.0f; + setState(STATE_PLUGIN_LOADED); } else { - // connect failed setState(STATE_ERROR); } + } break; - - case STATE_CONNECTED: - sendMessageToParent(LLPluginMessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hello")); - setState(STATE_PLUGIN_LOADING); + + case STATE_PLUGIN_LOADED: + { + setState(STATE_PLUGIN_INITIALIZING); + LLPluginMessage message("base", "init"); + sendMessageToPlugin(message); + } + break; + + case STATE_PLUGIN_INITIALIZING: + // waiting for init_response... break; - - case STATE_PLUGIN_LOADING: - if(!mPluginFile.empty()) + + case STATE_RUNNING: + if (mInstance != NULL) + { + // Provide some time to the plugin + LLPluginMessage message("base", "idle"); + message.setValueReal("time", PLUGIN_IDLE_SECONDS); + sendMessageToPlugin(message); + + mInstance->idle(); + + if (mHeartbeat.hasExpired()) { - mInstance = new LLPluginInstance(this); - if(mInstance->load(mPluginDir, mPluginFile) == 0) - { - mHeartbeat.start(); - mHeartbeat.setTimerExpirySec(HEARTBEAT_SECONDS); - mCPUElapsed = 0.0f; - setState(STATE_PLUGIN_LOADED); - } - else - { - setState(STATE_ERROR); - } + + // This just proves that we're not stuck down inside the plugin code. + LLPluginMessage heartbeat(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "heartbeat"); + + // Calculate the approximage CPU usage fraction (floating point value between 0 and 1) used by the plugin this heartbeat cycle. + // Note that this will not take into account any threads or additional processes the plugin spawns, but it's a first approximation. + // If we could write OS-specific functions to query the actual CPU usage of this process, that would be a better approximation. + heartbeat.setValueReal("cpu_usage", mCPUElapsed / mHeartbeat.getElapsedTimeF64()); + + sendMessageToParent(heartbeat); + + mHeartbeat.reset(); + mHeartbeat.setTimerExpirySec(HEARTBEAT_SECONDS); + mCPUElapsed = 0.0f; } + } + // receivePluginMessage will transition to STATE_UNLOADING break; - - case STATE_PLUGIN_LOADED: - { - setState(STATE_PLUGIN_INITIALIZING); - LLPluginMessage message("base", "init"); - sendMessageToPlugin(message); - } + + case STATE_SHUTDOWNREQ: + // set next state first thing in case "cleanup" message advances state. + setState(STATE_UNLOADING); + mWaitGoodbye.setTimerExpirySec(GOODBYE_SECONDS); + + if (mInstance != NULL) + { + sendMessageToPlugin(LLPluginMessage("base", "cleanup")); + } break; - - case STATE_PLUGIN_INITIALIZING: - // waiting for init_response... + + case STATE_UNLOADING: + // waiting for goodbye from plugin. + if (mWaitGoodbye.hasExpired()) + { + LL_WARNS() << "Wait for goodbye expired. Advancing to UNLOADED" << LL_ENDL; + setState(STATE_UNLOADED); + } + break; + + case STATE_UNLOADED: + killSockets(); + delete mInstance; + mInstance = NULL; + setState(STATE_DONE); + break; + + case STATE_ERROR: + // Close the socket to the launcher + killSockets(); + // TODO: Where do we go from here? Just exit()? + setState(STATE_DONE); + break; + + case STATE_DONE: + // just sit here. break; - - case STATE_RUNNING: - if(mInstance != NULL) - { - // Provide some time to the plugin - LLPluginMessage message("base", "idle"); - message.setValueReal("time", PLUGIN_IDLE_SECONDS); - sendMessageToPlugin(message); - - mInstance->idle(); - - if(mHeartbeat.hasExpired()) - { - - // This just proves that we're not stuck down inside the plugin code. - LLPluginMessage heartbeat(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "heartbeat"); - - // Calculate the approximage CPU usage fraction (floating point value between 0 and 1) used by the plugin this heartbeat cycle. - // Note that this will not take into account any threads or additional processes the plugin spawns, but it's a first approximation. - // If we could write OS-specific functions to query the actual CPU usage of this process, that would be a better approximation. - heartbeat.setValueReal("cpu_usage", mCPUElapsed / mHeartbeat.getElapsedTimeF64()); - - sendMessageToParent(heartbeat); - - mHeartbeat.reset(); - mHeartbeat.setTimerExpirySec(HEARTBEAT_SECONDS); - mCPUElapsed = 0.0f; - } - } - // receivePluginMessage will transition to STATE_UNLOADING - break; - - case STATE_SHUTDOWNREQ: - if (mInstance != NULL) - { - sendMessageToPlugin(LLPluginMessage("base", "cleanup")); - delete mInstance; - mInstance = NULL; - } - setState(STATE_UNLOADING); - mWaitGoodbye.setTimerExpirySec(GOODBYE_SECONDS); - break; - - case STATE_UNLOADING: - // waiting for goodbye from plugin. - if (mWaitGoodbye.hasExpired()) - { - LL_WARNS() << "Wait for goodbye expired. Advancing to UNLOADED" << LL_ENDL; - setState(STATE_UNLOADED); - } - break; - - case STATE_UNLOADED: - killSockets(); - setState(STATE_DONE); - break; - - case STATE_ERROR: - // Close the socket to the launcher - killSockets(); - // TODO: Where do we go from here? Just exit()? - setState(STATE_DONE); - break; - - case STATE_DONE: - // just sit here. - break; } - + } while (idle_again); } void LLPluginProcessChild::sleep(F64 seconds) { deliverQueuedMessages(); - if(mMessagePipe) + if (mMessagePipe) { mMessagePipe->pump(seconds); } @@ -253,7 +260,7 @@ void LLPluginProcessChild::sleep(F64 seconds) void LLPluginProcessChild::pump(void) { deliverQueuedMessages(); - if(mMessagePipe) + if (mMessagePipe) { mMessagePipe->pump(0.0f); } @@ -267,26 +274,26 @@ void LLPluginProcessChild::pump(void) bool LLPluginProcessChild::isRunning(void) { bool result = false; - - if(mState == STATE_RUNNING) + + if (mState == STATE_RUNNING) result = true; - + return result; } bool LLPluginProcessChild::isDone(void) { bool result = false; - - switch(mState) + + switch (mState) { - case STATE_DONE: + case STATE_DONE: result = true; break; - default: + default: break; } - + return result; } @@ -295,12 +302,12 @@ void LLPluginProcessChild::sendMessageToPlugin(const LLPluginMessage &message) if (mInstance) { std::string buffer = message.generate(); - + LL_DEBUGS("Plugin") << "Sending to plugin: " << buffer << LL_ENDL; LLTimer elapsed; - + mInstance->sendMessage(buffer); - + mCPUElapsed += elapsed.getElapsedTimeF64(); } else @@ -328,11 +335,11 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message) LLPluginMessage parsed; parsed.parse(message); - if(mBlockingRequest) + if (mBlockingRequest) { // We're blocking the plugin waiting for a response. - if(parsed.hasValue("blocking_response")) + if (parsed.hasValue("blocking_response")) { // This is the message we've been waiting for -- fall through and send it immediately. mBlockingResponseReceived = true; @@ -344,34 +351,34 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message) return; } } - + bool passMessage = true; - + // FIXME: how should we handle queueing here? - + { std::string message_class = parsed.getClass(); - if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL) + if (message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL) { passMessage = false; - + std::string message_name = parsed.getName(); - if(message_name == "load_plugin") + if (message_name == "load_plugin") { mPluginFile = parsed.getValue("file"); mPluginDir = parsed.getValue("dir"); } - else if (message_name == "shutdown_plugin") - { - setState(STATE_SHUTDOWNREQ); - } - else if(message_name == "shm_add") + else if (message_name == "shutdown_plugin") + { + setState(STATE_SHUTDOWNREQ); + } + else if (message_name == "shm_add") { std::string name = parsed.getValue("name"); size_t size = (size_t)parsed.getValueS32("size"); - + sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); - if(iter != mSharedMemoryRegions.end()) + if (iter != mSharedMemoryRegions.end()) { // Need to remove the old region first LL_WARNS("Plugin") << "Adding a duplicate shared memory segment!" << LL_ENDL; @@ -380,20 +387,20 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message) { // This is a new region LLPluginSharedMemory *region = new LLPluginSharedMemory; - if(region->attach(name, size)) + if (region->attach(name, size)) { mSharedMemoryRegions.insert(sharedMemoryRegionsType::value_type(name, region)); - + std::stringstream addr; addr << region->getMappedAddress(); - + // Send the add notification to the plugin LLPluginMessage message("base", "shm_added"); message.setValue("name", name); message.setValueS32("size", (S32)size); message.setValuePointer("address", region->getMappedAddress()); sendMessageToPlugin(message); - + // and send the response to the parent message.setMessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_add_response"); message.setValue("name", name); @@ -405,13 +412,13 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message) delete region; } } - + } - else if(message_name == "shm_remove") + else if (message_name == "shm_remove") { std::string name = parsed.getValue("name"); sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); - if(iter != mSharedMemoryRegions.end()) + if (iter != mSharedMemoryRegions.end()) { // forward the remove request to the plugin -- its response will trigger us to detach the segment. LLPluginMessage message("base", "shm_remove"); @@ -423,20 +430,20 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message) LL_WARNS("Plugin") << "shm_remove for unknown memory segment!" << LL_ENDL; } } - else if(message_name == "sleep_time") + else if (message_name == "sleep_time") { mSleepTime = llmax(parsed.getValueReal("time"), 1.0 / 100.0); // clamp to maximum of 100Hz } - else if(message_name == "crash") + else if (message_name == "crash") { // Crash the plugin LL_ERRS("Plugin") << "Plugin crash requested." << LL_ENDL; } - else if(message_name == "hang") + else if (message_name == "hang") { // Hang the plugin LL_WARNS("Plugin") << "Plugin hang requested." << LL_ENDL; - while(1) + while (1) { // wheeeeeeeee...... } @@ -447,8 +454,8 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message) } } } - - if(passMessage && mInstance != NULL) + + if (passMessage && mInstance != NULL) { LLTimer elapsed; @@ -458,50 +465,50 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message) } } -/* virtual */ +/* virtual */ void LLPluginProcessChild::receivePluginMessage(const std::string &message) { LL_DEBUGS("Plugin") << "Received from plugin: " << message << LL_ENDL; - - if(mBlockingRequest) + + if (mBlockingRequest) { // LL_ERRS("Plugin") << "Can't send a message while already waiting on a blocking request -- aborting!" << LL_ENDL; } - + // Incoming message from the plugin instance bool passMessage = true; // FIXME: how should we handle queueing here? - + // Intercept certain base messages (responses to ones sent by this class) { // Decode this message LLPluginMessage parsed; parsed.parse(message); - - if(parsed.hasValue("blocking_request")) + + if (parsed.hasValue("blocking_request")) { mBlockingRequest = true; } std::string message_class = parsed.getClass(); - if(message_class == "base") + if (message_class == "base") { std::string message_name = parsed.getName(); - if(message_name == "init_response") + if (message_name == "init_response") { // The plugin has finished initializing. setState(STATE_RUNNING); // Don't pass this message up to the parent passMessage = false; - + LLPluginMessage new_message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin_response"); LLSD versions = parsed.getValueLLSD("versions"); new_message.setValueLLSD("versions", versions); - - if(parsed.hasValue("plugin_version")) + + if (parsed.hasValue("plugin_version")) { std::string plugin_version = parsed.getValue("plugin_version"); new_message.setValueLLSD("plugin_version", plugin_version); @@ -510,25 +517,25 @@ void LLPluginProcessChild::receivePluginMessage(const std::string &message) // Let the parent know it's loaded and initialized. sendMessageToParent(new_message); } - else if (message_name == "goodbye") - { - setState(STATE_UNLOADED); - } - else if(message_name == "shm_remove_response") + else if (message_name == "goodbye") + { + setState(STATE_UNLOADED); + } + else if (message_name == "shm_remove_response") { // Don't pass this message up to the parent passMessage = false; std::string name = parsed.getValue("name"); - sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); - if(iter != mSharedMemoryRegions.end()) + sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); + if (iter != mSharedMemoryRegions.end()) { // detach the shared memory region iter->second->detach(); - + // and remove it from our map mSharedMemoryRegions.erase(iter); - + // Finally, send the response to the parent. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_remove_response"); message.setValue("name", name); @@ -541,19 +548,19 @@ void LLPluginProcessChild::receivePluginMessage(const std::string &message) } } } - - if(passMessage) + + if (passMessage) { LL_DEBUGS("Plugin") << "Passing through to parent: " << message << LL_ENDL; writeMessageRaw(message); } - - while(mBlockingRequest) + + while (mBlockingRequest) { // The plugin wants to block and wait for a response to this message. sleep(mSleepTime); // this will pump the message pipe and process messages - if(mBlockingResponseReceived || mSocketError != APR_SUCCESS || (mMessagePipe == NULL)) + if (mBlockingResponseReceived || mSocketError != APR_SUCCESS || (mMessagePipe == NULL)) { // Response has been received, or we've hit an error state. Stop waiting. mBlockingRequest = false; @@ -566,14 +573,14 @@ void LLPluginProcessChild::receivePluginMessage(const std::string &message) void LLPluginProcessChild::setState(EState state) { LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL; - mState = state; + mState = state; }; void LLPluginProcessChild::deliverQueuedMessages() { - if(!mBlockingRequest) + if (!mBlockingRequest) { - while(!mMessageQueue.empty()) + while (!mMessageQueue.empty()) { receiveMessageRaw(mMessageQueue.front()); mMessageQueue.pop(); diff --git a/indra/llplugin/slplugin/slplugin.cpp b/indra/llplugin/slplugin/slplugin.cpp index 684bcf1207..b960565416 100644 --- a/indra/llplugin/slplugin/slplugin.cpp +++ b/indra/llplugin/slplugin/slplugin.cpp @@ -100,33 +100,8 @@ LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter( BOOL PreventSetUnhandledExceptionFilter() { -// WARNING: This won't work on 64-bit Windows systems so we turn it off it. -// It should work for any flavor of 32-bit Windows we care about. -// If it's off, sometimes you will see an OS message when a plugin crashes -#ifndef _WIN64 - HMODULE hKernel32 = LoadLibraryA( "kernel32.dll" ); - if ( NULL == hKernel32 ) - return FALSE; - - void *pOrgEntry = GetProcAddress( hKernel32, "SetUnhandledExceptionFilter" ); - if( NULL == pOrgEntry ) - return FALSE; - - unsigned char newJump[ 100 ]; - DWORD dwOrgEntryAddr = (DWORD)pOrgEntry; - dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far - void *pNewFunc = &MyDummySetUnhandledExceptionFilter; - DWORD dwNewEntryAddr = (DWORD) pNewFunc; - DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr; - - newJump[ 0 ] = 0xE9; // JMP absolute - memcpy( &newJump[ 1 ], &dwRelativeAddr, sizeof( pNewFunc ) ); - SIZE_T bytesWritten; - BOOL bRet = WriteProcessMemory( GetCurrentProcess(), pOrgEntry, newJump, sizeof( pNewFunc ) + 1, &bytesWritten ); - return bRet; -#else - return FALSE; -#endif + // remove the scary stuff that also isn't supported on 64 bit Windows + return TRUE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 301ae7f9c4..5ec0ada6eb 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -3800,7 +3800,7 @@ LLWindowCallbacks::DragNDropResult LLWindowWin32::completeDragNDropRequest( cons // When it handled the message, the value to be returned from // the Window Procedure is set to *result. -BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result) +BOOL LLWindowWin32::handleImeRequests(WPARAM request, LPARAM param, LRESULT *result) { if ( mPreeditor ) { diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index 39ef9b31a4..059a008c45 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -148,7 +148,7 @@ protected: U32 fillReconvertString(const LLWString &text, S32 focus, S32 focus_length, RECONVERTSTRING *reconvert_string); void handleStartCompositionMessage(); void handleCompositionMessage(U32 indexes); - BOOL handleImeRequests(U32 request, U32 param, LRESULT *result); + BOOL handleImeRequests(WPARAM request, LPARAM param, LRESULT *result); protected: // diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt index 1eadce825e..1a5cc8ec9a 100644 --- a/indra/media_plugins/CMakeLists.txt +++ b/indra/media_plugins/CMakeLists.txt @@ -5,14 +5,17 @@ add_subdirectory(base) if (LINUX) add_subdirectory(gstreamer010) add_subdirectory(libvlc) + add_subdirectory(example) endif (LINUX) if (DARWIN) add_subdirectory(cef) add_subdirectory(libvlc) + add_subdirectory(example) endif (DARWIN) if (WINDOWS) add_subdirectory(cef) add_subdirectory(libvlc) + add_subdirectory(example) endif (WINDOWS) diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 906a5ff6e7..69717be91f 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -55,7 +55,7 @@ public: private: bool init(); - void onPageChangedCallback(const unsigned char* pixels, int x, int y, const int width, const int height, bool is_popup); + void onPageChangedCallback(const unsigned char* pixels, int x, int y, const int width, const int height); void onCustomSchemeURLCallback(std::string url); void onConsoleMessageCallback(std::string message, std::string source, int line); void onStatusMessageCallback(std::string value); @@ -84,6 +84,7 @@ private: bool mCookiesEnabled; bool mPluginsEnabled; bool mJavascriptEnabled; + bool mDisableGPU; std::string mUserAgentSubtring; std::string mAuthUsername; std::string mAuthPassword; @@ -95,12 +96,6 @@ private: std::string mCookiePath; std::string mPickedFile; dullahan* mCEFLib; - - U8 *mPopupBuffer; - U32 mPopupW; - U32 mPopupH; - U32 mPopupX; - U32 mPopupY; }; //////////////////////////////////////////////////////////////////////////////// @@ -117,6 +112,7 @@ MediaPluginBase(host_send_func, host_user_data) mCookiesEnabled = true; mPluginsEnabled = false; mJavascriptEnabled = true; + mDisableGPU = true; mUserAgentSubtring = ""; mAuthUsername = ""; mAuthPassword = ""; @@ -129,18 +125,13 @@ MediaPluginBase(host_send_func, host_user_data) mPickedFile = ""; mCEFLib = new dullahan(); - mPopupBuffer = NULL; - mPopupW = 0; - mPopupH = 0; - mPopupX = 0; - mPopupY = 0; } //////////////////////////////////////////////////////////////////////////////// // MediaPluginCEF::~MediaPluginCEF() { - delete[] mPopupBuffer; + mCEFLib->shutdown(); } //////////////////////////////////////////////////////////////////////////////// @@ -161,56 +152,13 @@ void MediaPluginCEF::postDebugMessage(const std::string& msg) //////////////////////////////////////////////////////////////////////////////// // -void MediaPluginCEF::onPageChangedCallback(const unsigned char* pixels, int x, int y, const int width, const int height, bool is_popup) +void MediaPluginCEF::onPageChangedCallback(const unsigned char* pixels, int x, int y, const int width, const int height) { - if( is_popup ) - { - delete mPopupBuffer; - mPopupBuffer = NULL; - mPopupH = 0; - mPopupW = 0; - mPopupX = 0; - mPopupY = 0; - } - if( mPixels && pixels ) { - if (is_popup) + if (mWidth == width && mHeight == height) { - if( width > 0 && height> 0 ) - { - mPopupBuffer = new U8[ width * height * mDepth ]; - memcpy( mPopupBuffer, pixels, width * height * mDepth ); - mPopupH = height; - mPopupW = width; - mPopupX = x; - mPopupY = mHeight - y - height; - } - } - else - { - if (mWidth == width && mHeight == height) - { - memcpy(mPixels, pixels, mWidth * mHeight * mDepth); - } - if( mPopupBuffer && mPopupH && mPopupW ) - { - U32 bufferSize = mWidth * mHeight * mDepth; - U32 popupStride = mPopupW * mDepth; - U32 bufferStride = mWidth * mDepth; - int dstY = mPopupY; - - int src = 0; - int dst = dstY * mWidth * mDepth + mPopupX * mDepth; - - for( int line = 0; dst + popupStride < bufferSize && line < mPopupH; ++line ) - { - memcpy( mPixels + dst, mPopupBuffer + src, popupStride ); - src += popupStride; - dst += bufferStride; - } - } - + memcpy(mPixels, pixels, mWidth * mHeight * mDepth); } setDirty(0, 0, mWidth, mHeight); } @@ -258,10 +206,10 @@ void MediaPluginCEF::onLoadStartCallback() // void MediaPluginCEF::onRequestExitCallback() { - mCEFLib->shutdown(); - LLPluginMessage message("base", "goodbye"); sendMessage(message); + + mDeleteMe = true; } //////////////////////////////////////////////////////////////////////////////// @@ -477,7 +425,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) if (message_name == "init") { // event callbacks from Dullahan - mCEFLib->setOnPageChangedCallback(std::bind(&MediaPluginCEF::onPageChangedCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6)); + mCEFLib->setOnPageChangedCallback(std::bind(&MediaPluginCEF::onPageChangedCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); mCEFLib->setOnCustomSchemeURLCallback(std::bind(&MediaPluginCEF::onCustomSchemeURLCallback, this, std::placeholders::_1)); mCEFLib->setOnConsoleMessageCallback(std::bind(&MediaPluginCEF::onConsoleMessageCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); mCEFLib->setOnStatusMessageCallback(std::bind(&MediaPluginCEF::onStatusMessageCallback, this, std::placeholders::_1)); @@ -499,6 +447,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) settings.cache_path = mCachePath; settings.cookie_store_path = mCookiePath; settings.cookies_enabled = mCookiesEnabled; + settings.disable_gpu = mDisableGPU; settings.flash_enabled = mPluginsEnabled; settings.flip_mouse_y = false; settings.flip_pixels_y = true; @@ -755,6 +704,10 @@ void MediaPluginCEF::receiveMessage(const char* message_string) { mJavascriptEnabled = message_in.getValueBoolean("enable"); } + else if (message_name == "gpu_disabled") + { + mDisableGPU = message_in.getValueBoolean("disable"); + } } else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) { diff --git a/indra/media_plugins/example/CMakeLists.txt b/indra/media_plugins/example/CMakeLists.txt index d2a17b1d76..42eb378172 100644 --- a/indra/media_plugins/example/CMakeLists.txt +++ b/indra/media_plugins/example/CMakeLists.txt @@ -67,7 +67,7 @@ if (WINDOWS) set_target_properties( media_plugin_example PROPERTIES - LINK_FLAGS "/MANIFEST:NO" + LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /LTCG /NODEFAULTLIB:LIBCMT" ) endif (WINDOWS) diff --git a/indra/media_plugins/example/media_plugin_example.cpp b/indra/media_plugins/example/media_plugin_example.cpp index 66c00cd58c..c296a0413d 100644 --- a/indra/media_plugins/example/media_plugin_example.cpp +++ b/indra/media_plugins/example/media_plugin_example.cpp @@ -1,30 +1,30 @@ /** - * @file media_plugin_example.cpp - * @brief Example 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 - */ +* @file media_plugin_example.cpp +* @brief Example 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" @@ -38,375 +38,354 @@ //////////////////////////////////////////////////////////////////////////////// // -class MediaPluginExample : - public MediaPluginBase +class mediaPluginExample : + public MediaPluginBase { - public: - MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ); - ~MediaPluginExample(); - - /*virtual*/ void receiveMessage( const char* message_string ); - - private: - bool init(); - void update( F64 milliseconds ); - void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ); - bool mFirstTime; - - time_t mLastUpdateTime; - enum Constants { ENumObjects = 10 }; - unsigned char* mBackgroundPixels; - int mColorR[ ENumObjects ]; - int mColorG[ ENumObjects ]; - int mColorB[ ENumObjects ]; - int mXpos[ ENumObjects ]; - int mYpos[ ENumObjects ]; - int mXInc[ ENumObjects ]; - int mYInc[ ENumObjects ]; - int mBlockSize[ ENumObjects ]; - bool mMouseButtonDown; - bool mStopAction; +public: + mediaPluginExample(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~mediaPluginExample(); + + /*virtual*/ void receiveMessage(const char* message_string); + +private: + bool init(); + void update(F64 milliseconds); + bool mFirstTime; + + time_t mLastUpdateTime; + enum Constants { ENumObjects = 64 }; + unsigned char* mBackgroundPixels; + int mColorR[ENumObjects]; + int mColorG[ENumObjects]; + int mColorB[ENumObjects]; + int mXpos[ENumObjects]; + int mYpos[ENumObjects]; + int mXInc[ENumObjects]; + int mYInc[ENumObjects]; + int mBlockSize[ENumObjects]; }; //////////////////////////////////////////////////////////////////////////////// // -MediaPluginExample::MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ) : - MediaPluginBase( host_send_func, host_user_data ) +mediaPluginExample::mediaPluginExample(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) : +MediaPluginBase(host_send_func, host_user_data) { - mFirstTime = true; - mWidth = 0; - mHeight = 0; - mDepth = 4; - mPixels = 0; - mMouseButtonDown = false; - mStopAction = false; - mLastUpdateTime = 0; + mFirstTime = true; + mTextureWidth = 0; + mTextureHeight = 0; + mWidth = 0; + mHeight = 0; + mDepth = 4; + mPixels = 0; + mLastUpdateTime = 0; + mBackgroundPixels = 0; } //////////////////////////////////////////////////////////////////////////////// // -MediaPluginExample::~MediaPluginExample() +mediaPluginExample::~mediaPluginExample() { } //////////////////////////////////////////////////////////////////////////////// // -void MediaPluginExample::receiveMessage( const char* message_string ) +void mediaPluginExample::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 = "Example plugin 1.0..0"; - 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") - { - } - else if(message_name == "shm_added") - { - SharedSegmentInfo info; - info.mAddress = message_in.getValuePointer("address"); - info.mSize = (size_t)message_in.getValueS32("size"); - std::string name = message_in.getValue("name"); - - mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - - } - else if(message_name == "shm_remove") - { - std::string name = message_in.getValue("name"); - - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if(iter != mSharedSegments.end()) - { - if(mPixels == iter->second.mAddress) - { - // This is the currently active pixel buffer. Make sure we stop drawing to it. - mPixels = NULL; - mTextureSegmentName.clear(); - } - mSharedSegments.erase(iter); - } - 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) - { - if(message_name == "init") - { - // 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); - message.setValueU32("format", GL_RGBA); - message.setValueU32("type", GL_UNSIGNED_BYTE); - message.setValueBoolean("coords_opengl", true); - sendMessage(message); - } - else if(message_name == "size_change") - { - std::string name = message_in.getValue("name"); - S32 width = message_in.getValueS32("width"); - S32 height = message_in.getValueS32("height"); - S32 texture_width = message_in.getValueS32("texture_width"); - S32 texture_height = message_in.getValueS32("texture_height"); - - 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; - }; - }; - - 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") - { - } - else if(message_name == "mouse_event") - { - std::string event = message_in.getValue("event"); - if(event == "down") - { - - } - else if(event == "up") - { - } - else if(event == "double_click") - { - } - } - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; - }; - } + // 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 = "Example plugin 0.0.0"; + 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") + { + LLPluginMessage message("base", "goodbye"); + sendMessage(message); + + mDeleteMe = true; + } + else if (message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if (message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if (iter != mSharedSegments.end()) + { + if (mPixels == iter->second.mAddress) + { + // This is the currently active pixel buffer. Make sure we stop drawing to it. + mPixels = NULL; + mTextureSegmentName.clear(); + } + mSharedSegments.erase(iter); + } + 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) + { + if (message_name == "init") + { + // 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_RGBA); + message.setValueU32("type", GL_UNSIGNED_BYTE); + message.setValueBoolean("coords_opengl", true); + sendMessage(message); + } + else if (message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + 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; + }; + }; + + 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); + + mFirstTime = true; + mLastUpdateTime = 0; + + } + else if (message_name == "load_uri") + { + } + else if (message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + if (event == "down") + { + + } + else if (event == "up") + { + } + else if (event == "double_click") + { + } + } + } + else + { + }; + } } //////////////////////////////////////////////////////////////////////////////// // -void MediaPluginExample::write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ) +void mediaPluginExample::update(F64 milliseconds) { - // make sure we don't write outside the buffer - if ( ( x < 0 ) || ( x >= mWidth ) || ( y < 0 ) || ( y >= mHeight ) ) - return; - - if ( mBackgroundPixels != NULL ) - { - unsigned char *pixel = mBackgroundPixels; - pixel += y * mWidth * mDepth; - pixel += ( x * mDepth ); - pixel[ 0 ] = b; - pixel[ 1 ] = g; - pixel[ 2 ] = r; - - setDirty( x, y, x + 1, y + 1 ); - }; -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginExample::update( F64 milliseconds ) -{ - if ( mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048 ) - return; - - if ( mPixels == 0 ) - return; - - if ( mFirstTime ) - { - for( int n = 0; n < ENumObjects; ++n ) - { - mXpos[ n ] = ( mWidth / 2 ) + rand() % ( mWidth / 16 ) - ( mWidth / 32 ); - mYpos[ n ] = ( mHeight / 2 ) + rand() % ( mHeight / 16 ) - ( mHeight / 32 ); - - mColorR[ n ] = rand() % 0x60 + 0x60; - mColorG[ n ] = rand() % 0x60 + 0x60; - mColorB[ n ] = rand() % 0x60 + 0x60; - - mXInc[ n ] = 0; - while ( mXInc[ n ] == 0 ) - mXInc[ n ] = rand() % 7 - 3; - - mYInc[ n ] = 0; - while ( mYInc[ n ] == 0 ) - mYInc[ n ] = rand() % 9 - 4; - - mBlockSize[ n ] = rand() % 0x30 + 0x10; - }; - - delete [] mBackgroundPixels; - - mBackgroundPixels = new unsigned char[ mWidth * mHeight * mDepth ]; - - mFirstTime = false; - }; - - if ( mStopAction ) - return; - - if ( time( NULL ) > mLastUpdateTime + 3 ) - { - const int num_squares = rand() % 20 + 4; - int sqr1_r = rand() % 0x80 + 0x20; - int sqr1_g = rand() % 0x80 + 0x20; - int sqr1_b = rand() % 0x80 + 0x20; - int sqr2_r = rand() % 0x80 + 0x20; - int sqr2_g = rand() % 0x80 + 0x20; - int sqr2_b = rand() % 0x80 + 0x20; - - for ( int y1 = 0; y1 < num_squares; ++y1 ) - { - for ( int x1 = 0; x1 < num_squares; ++x1 ) - { - int px_start = mWidth * x1 / num_squares; - int px_end = ( mWidth * ( x1 + 1 ) ) / num_squares; - int py_start = mHeight * y1 / num_squares; - int py_end = ( mHeight * ( y1 + 1 ) ) / num_squares; - - for( int y2 = py_start; y2 < py_end; ++y2 ) - { - for( int x2 = px_start; x2 < px_end; ++x2 ) - { - int rowspan = mWidth * mDepth; - - if ( ( y1 % 2 ) ^ ( x1 % 2 ) ) - { - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr1_r; - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr1_g; - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr1_b; - } - else - { - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr2_r; - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr2_g; - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr2_b; - }; - }; - }; - }; - }; - - time( &mLastUpdateTime ); - }; - - memcpy( mPixels, mBackgroundPixels, mWidth * mHeight * mDepth ); - - for( int n = 0; n < ENumObjects; ++n ) - { - if ( rand() % 50 == 0 ) - { - mXInc[ n ] = 0; - while ( mXInc[ n ] == 0 ) - mXInc[ n ] = rand() % 7 - 3; - - mYInc[ n ] = 0; - while ( mYInc[ n ] == 0 ) - mYInc[ n ] = rand() % 9 - 4; - }; - - if ( mXpos[ n ] + mXInc[ n ] < 0 || mXpos[ n ] + mXInc[ n ] >= mWidth - mBlockSize[ n ] ) - mXInc[ n ]= -mXInc[ n ]; - - if ( mYpos[ n ] + mYInc[ n ] < 0 || mYpos[ n ] + mYInc[ n ] >= mHeight - mBlockSize[ n ] ) - mYInc[ n ]= -mYInc[ n ]; - - mXpos[ n ] += mXInc[ n ]; - mYpos[ n ] += mYInc[ n ]; - - for( int y = 0; y < mBlockSize[ n ]; ++y ) - { - for( int x = 0; x < mBlockSize[ n ]; ++x ) - { - mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 0 ] = mColorR[ n ]; - mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 1 ] = mColorG[ n ]; - mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 2 ] = mColorB[ n ]; - }; - }; - }; - - setDirty( 0, 0, mWidth, mHeight ); + if (mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048) + return; + + if (mPixels == 0) + return; + + if (mFirstTime) + { + for (int n = 0; n < ENumObjects; ++n) + { + mXpos[n] = (mWidth / 2) + rand() % (mWidth / 16) - (mWidth / 32); + mYpos[n] = (mHeight / 2) + rand() % (mHeight / 16) - (mHeight / 32); + + mColorR[n] = rand() % 0x60 + 0x60; + mColorG[n] = rand() % 0x60 + 0x60; + mColorB[n] = rand() % 0x60 + 0x60; + + mXInc[n] = 0; + while (mXInc[n] == 0) + mXInc[n] = rand() % 7 - 3; + + mYInc[n] = 0; + while (mYInc[n] == 0) + mYInc[n] = rand() % 9 - 4; + + mBlockSize[n] = rand() % 0x30 + 0x10; + }; + + delete[] mBackgroundPixels; + + mBackgroundPixels = new unsigned char[mWidth * mHeight * mDepth]; + + mFirstTime = false; + }; + + if (time(NULL) > mLastUpdateTime + 3) + { + const int num_squares = rand() % 20 + 4; + int sqr1_r = rand() % 0x80 + 0x20; + int sqr1_g = rand() % 0x80 + 0x20; + int sqr1_b = rand() % 0x80 + 0x20; + int sqr2_r = rand() % 0x80 + 0x20; + int sqr2_g = rand() % 0x80 + 0x20; + int sqr2_b = rand() % 0x80 + 0x20; + + for (int y1 = 0; y1 < num_squares; ++y1) + { + for (int x1 = 0; x1 < num_squares; ++x1) + { + int px_start = mWidth * x1 / num_squares; + int px_end = (mWidth * (x1 + 1)) / num_squares; + int py_start = mHeight * y1 / num_squares; + int py_end = (mHeight * (y1 + 1)) / num_squares; + + for (int y2 = py_start; y2 < py_end; ++y2) + { + for (int x2 = px_start; x2 < px_end; ++x2) + { + int rowspan = mWidth * mDepth; + + if ((y1 % 2) ^ (x1 % 2)) + { + mBackgroundPixels[y2 * rowspan + x2 * mDepth + 0] = sqr1_r; + mBackgroundPixels[y2 * rowspan + x2 * mDepth + 1] = sqr1_g; + mBackgroundPixels[y2 * rowspan + x2 * mDepth + 2] = sqr1_b; + } + else + { + mBackgroundPixels[y2 * rowspan + x2 * mDepth + 0] = sqr2_r; + mBackgroundPixels[y2 * rowspan + x2 * mDepth + 1] = sqr2_g; + mBackgroundPixels[y2 * rowspan + x2 * mDepth + 2] = sqr2_b; + }; + }; + }; + }; + }; + + time(&mLastUpdateTime); + }; + + memcpy(mPixels, mBackgroundPixels, mWidth * mHeight * mDepth); + + for (int n = 0; n < ENumObjects; ++n) + { + if (rand() % 50 == 0) + { + mXInc[n] = 0; + while (mXInc[n] == 0) + mXInc[n] = rand() % 7 - 3; + + mYInc[n] = 0; + while (mYInc[n] == 0) + mYInc[n] = rand() % 9 - 4; + }; + + if (mXpos[n] + mXInc[n] < 0 || mXpos[n] + mXInc[n] >= mWidth - mBlockSize[n]) + mXInc[n] = -mXInc[n]; + + if (mYpos[n] + mYInc[n] < 0 || mYpos[n] + mYInc[n] >= mHeight - mBlockSize[n]) + mYInc[n] = -mYInc[n]; + + mXpos[n] += mXInc[n]; + mYpos[n] += mYInc[n]; + + for (int y = 0; y < mBlockSize[n]; ++y) + { + for (int x = 0; x < mBlockSize[n]; ++x) + { + mPixels[(mXpos[n] + x) * mDepth + (mYpos[n] + y) * mDepth * mWidth + 0] = mColorR[n]; + mPixels[(mXpos[n] + x) * mDepth + (mYpos[n] + y) * mDepth * mWidth + 1] = mColorG[n]; + mPixels[(mXpos[n] + x) * mDepth + (mYpos[n] + y) * mDepth * mWidth + 2] = mColorB[n]; + }; + }; + }; + + setDirty(0, 0, mWidth, mHeight); }; //////////////////////////////////////////////////////////////////////////////// // -bool MediaPluginExample::init() +bool mediaPluginExample::init() { - LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" ); - message.setValue( "name", "Example Plugin" ); - sendMessage( message ); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", "Example Plugin"); + sendMessage(message); - return true; + return true; }; //////////////////////////////////////////////////////////////////////////////// // -int init_media_plugin( LLPluginInstance::sendMessageFunction host_send_func, - void* host_user_data, - LLPluginInstance::sendMessageFunction *plugin_send_func, - void **plugin_user_data ) +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, + void* host_user_data, + LLPluginInstance::sendMessageFunction *plugin_send_func, + void **plugin_user_data) { - MediaPluginExample* self = new MediaPluginExample( host_send_func, host_user_data ); - *plugin_send_func = MediaPluginExample::staticReceiveMessage; - *plugin_user_data = ( void* )self; + mediaPluginExample* self = new mediaPluginExample(host_send_func, host_user_data); + *plugin_send_func = mediaPluginExample::staticReceiveMessage; + *plugin_user_data = (void*)self; - return 0; + return 0; } - diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 81a08182c7..62451e4856 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1749,6 +1749,7 @@ if (WINDOWS) SLPlugin media_plugin_cef media_plugin_libvlc + media_plugin_example winmm_shim windows-crash-logger ) diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index eb07b54d8d..71a33a0dc0 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -90,8 +90,11 @@ InstProgressFlags smooth colored # New colored smooth look SetOverwrite on # Overwrite files by default
AutoCloseWindow true # After all files install, close window
-InstallDir "%%$PROGRAMFILES%%\${INSTNAME}"
-InstallDirRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\${INSTNAME}" ""
+# initial location of install (default when not already installed)
+# note: Now we defer looking for existing install until onInit when we
+# are able to engage the 32/64 registry function
+InstallDir "%%PROGRAMFILES%%\${INSTNAME}"
+
UninstallText $(UninstallTextMsg)
DirText $(DirectoryChooseTitle) $(DirectoryChooseSetup)
Page directory dirPre
@@ -118,6 +121,8 @@ Var DO_UNINSTALL_V2 # If non-null, path to a previous Viewer 2 installation !insertmacro GetParameters
!insertmacro GetOptions
!include WinVer.nsh # For OS and SP detection
+!include 'LogicLib.nsh' # for value comparison
+!include "x64.nsh" # for 64bit detection
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre-directory page callback
@@ -136,7 +141,21 @@ FunctionEnd ;; entry to the language ID selector below
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function .onInit
+
%%ENGAGEREGISTRY%%
+
+# read the current location of the install for this version
+# if $0 is empty, this is the first time for this viewer name
+ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\\Linden Research, Inc.\\${INSTNAME}" ""
+
+# viewer with this name not installed before
+${If} $0 == ""
+ # nothing to do here
+${Else}
+ # use the value we got from registry as install location
+ StrCpy $INSTDIR $0
+${EndIf}
+
Call CheckCPUFlags # Make sure we have SSE2 support
Call CheckWindowsVersion # Don't install On unsupported systems
Push $0
@@ -195,7 +214,9 @@ FunctionEnd ;; Prep Uninstaller Section
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function un.onInit
+
%%ENGAGEREGISTRY%%
+
# Read language from registry and set for uninstaller. Key will be removed on successful uninstall
ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\${INSTNAME}" "InstallerLanguage"
IfErrors lbl_end
@@ -320,6 +341,10 @@ WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninst WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "UninstallString" '"$INSTDIR\uninst.exe"'
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "DisplayVersion" "${VERSION_LONG}"
WriteRegDWORD HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "EstimatedSize" "0x0001D500" # ~117 MB
+
+# from FS:Ansariel
+WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "DisplayIcon" '"$INSTDIR\$INSTEXE"'
+
# BUG-2707 Disable SEHOP for installed viewer.
WriteRegDWORD HKEY_LOCAL_MACHINE "Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\$INSTEXE" "DisableExceptionChainValidation" 1
@@ -561,7 +586,7 @@ FunctionEnd Function RemoveProgFilesOnInst
# Remove old SecondLife.exe to invalidate any old shortcuts to it that may be in non-standard locations. See MAINT-3575
-Delete "$INSTDIR\SecondLife.exe"
+Delete "$INSTDIR\$INSTEXE"
# Remove old shader files first so fallbacks will work. See DEV-5663
RMDir /r "$INSTDIR\app_settings\shaders"
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 9f05ee61bd..900075488f 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -604,7 +604,9 @@ void LLViewerMedia::updateMedia(void *dummy_arg) LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread")); // HACK: we always try to keep a spare running webkit plugin around to improve launch times. - createSpareBrowserMediaSource(); + // 2017-04-19 Removed CP - this doesn't appear to buy us much and consumes a lot of resources so + // removing it for now. + //createSpareBrowserMediaSource(); sAnyMediaShowing = false; sAnyMediaPlaying = false; diff --git a/indra/newview/skins/default/xui/en/mime_types.xml b/indra/newview/skins/default/xui/en/mime_types.xml index 8d8d546b24..8a810f32a6 100644 --- a/indra/newview/skins/default/xui/en/mime_types.xml +++ b/indra/newview/skins/default/xui/en/mime_types.xml @@ -133,18 +133,29 @@ media_plugin_libvlc </impl> </scheme> - <scheme name="libvlc"> - <label name="libvlc_label"> - LibVLC supported media - </label> - <widgettype> - movie - </widgettype> - <impl> - media_plugin_libvlc - </impl> - </scheme> - <mimetype name="blank"> + <scheme name="example"> + <label name="example_label"> + Example Plugin scheme trigger + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_example + </impl> + </scheme> + <scheme name="libvlc"> + <label name="libvlc_label"> + LibVLC supported media + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_libvlc + </impl> + </scheme> + <mimetype name="blank"> <label name="blank_label"> - None - </label> diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 3a8cd0c626..fba8a8b159 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -439,6 +439,12 @@ class WindowsManifest(ViewerManifest): self.path("media_plugin_libvlc.dll") self.end_prefix() + # Media plugins - Example (useful for debugging - not shipped with release viewer) + if self.channel_type() != 'release': + if self.prefix(src='../media_plugins/example/%s' % self.args['configuration'], dst="llplugin"): + self.path("media_plugin_example.dll") + self.end_prefix() + # CEF runtime files - debug if self.args['configuration'].lower() == 'debug': if self.prefix(src=os.path.join(os.pardir, 'packages', 'bin', 'debug'), dst="llplugin"): @@ -648,7 +654,7 @@ class WindowsManifest(ViewerManifest): "%%SOURCE%%":self.get_src_prefix(), "%%INST_VARS%%":inst_vars_template % substitution_strings, "%%INSTALL_FILES%%":self.nsi_file_commands(True), - "%%$PROGRAMFILES%%":program_files, + "%%PROGRAMFILES%%":program_files, "%%ENGAGEREGISTRY%%":engage_registry, "%%DELETE_FILES%%":self.nsi_file_commands(False)}) |