From 16cd4c5c4ba19a43cbc2757768ba4a5bb2e3647b Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 6 May 2011 16:08:24 +0200 Subject: [PATCH] Split plugin classes and derive AIFilePicker from BasicPluginBase (part 3). This commit deletes all indra/media_plugins and copied one-on-one the indra/plugins directory from my (imprudence) statemachine branch (which contains the AIFilePicker patch). git shows this as a lot of 'renamed' files because originally it was a rename. However, there are a lot of changes as well: it's both an upgrade to a newer plugin system (changes by LL) as well as an upgrade to my refactored plugin system with a file picker as plugin. Since this commit is a one-on-one copy, it disregards any changes that were in Singularity and not in imprudence in indra/media_plugins however. I will add those back in the next commit. --- indra/media_plugins/CMakeLists.txt | 15 - .../example/media_plugin_example.cpp | 412 ----- .../gstreamer010/llmediaimplgstreamer.h | 53 - .../llmediaimplgstreamer_syms.cpp | 167 -- .../gstreamer010/llmediaimplgstreamer_syms.h | 74 - .../llmediaimplgstreamer_syms_raw.inc | 51 - .../llmediaimplgstreamer_syms_rawv.inc | 5 - .../llmediaimplgstreamertriviallogging.h | 55 - .../webkit/dummy_volume_catcher.cpp | 58 - indra/media_plugins/webkit/volume_catcher.h | 54 - indra/plugins/CMakeLists.txt | 17 + indra/plugins/base_basic/CMakeLists.txt | 39 + .../plugins/base_basic/basic_plugin_base.cpp | 136 ++ .../base_basic/basic_plugin_base.exp} | 0 indra/plugins/base_basic/basic_plugin_base.h | 88 + .../base_media}/CMakeLists.txt | 11 +- .../base_media}/media_plugin_base.cpp | 70 +- .../plugins/base_media/media_plugin_base.exp | 2 + .../base_media}/media_plugin_base.h | 48 +- indra/plugins/example_basic/CMakeLists.txt | 68 + .../example_basic/basic_plugin_example.cpp | 123 ++ .../example_media}/CMakeLists.txt | 19 +- .../example_media/media_plugin_example.cpp | 490 ++++++ indra/plugins/filepicker/CMakeLists.txt | 81 + indra/plugins/filepicker/llfilepicker.cpp | 1414 +++++++++++++++++ indra/plugins/filepicker/llfilepicker.h | 231 +++ .../gstreamer010/CMakeLists.txt | 11 - .../gstreamer010/llmediaimplgstreamer.h | 60 + .../llmediaimplgstreamertriviallogging.h | 65 + .../llmediaimplgstreamervidplug.cpp | 201 ++- .../llmediaimplgstreamervidplug.h | 38 +- .../media_plugin_gstreamer010.cpp | 602 ++++--- .../quicktime/CMakeLists.txt | 3 +- .../quicktime/media_plugin_quicktime.cpp | 29 +- .../webkit/CMakeLists.txt | 20 +- indra/plugins/webkit/dummy_volume_catcher.cpp | 65 + .../webkit/linux_volume_catcher.cpp | 40 +- indra/plugins/webkit/linux_volume_catcher.h | 56 + .../webkit/linux_volume_catcher_pa_syms.inc | 0 .../linux_volume_catcher_paglib_syms.inc | 0 .../webkit/mac_volume_catcher.cpp | 37 +- .../webkit/media_plugin_webkit.cpp | 135 +- indra/plugins/webkit/volume_catcher.h | 61 + .../webkit/windows_volume_catcher.cpp | 39 +- 44 files changed, 3666 insertions(+), 1577 deletions(-) delete mode 100644 indra/media_plugins/CMakeLists.txt delete mode 100644 indra/media_plugins/example/media_plugin_example.cpp delete mode 100644 indra/media_plugins/gstreamer010/llmediaimplgstreamer.h delete mode 100644 indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp delete mode 100644 indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h delete mode 100644 indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc delete mode 100644 indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc delete mode 100644 indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h delete mode 100644 indra/media_plugins/webkit/dummy_volume_catcher.cpp delete mode 100644 indra/media_plugins/webkit/volume_catcher.h create mode 100644 indra/plugins/CMakeLists.txt create mode 100644 indra/plugins/base_basic/CMakeLists.txt create mode 100755 indra/plugins/base_basic/basic_plugin_base.cpp rename indra/{media_plugins/base/media_plugin_base.exp => plugins/base_basic/basic_plugin_base.exp} (100%) mode change 100755 => 100644 create mode 100755 indra/plugins/base_basic/basic_plugin_base.h rename indra/{media_plugins/base => plugins/base_media}/CMakeLists.txt (81%) rename indra/{media_plugins/base => plugins/base_media}/media_plugin_base.cpp (66%) mode change 100644 => 100755 create mode 100755 indra/plugins/base_media/media_plugin_base.exp rename indra/{media_plugins/base => plugins/base_media}/media_plugin_base.h (67%) mode change 100644 => 100755 create mode 100644 indra/plugins/example_basic/CMakeLists.txt create mode 100644 indra/plugins/example_basic/basic_plugin_example.cpp rename indra/{media_plugins/example => plugins/example_media}/CMakeLists.txt (83%) create mode 100755 indra/plugins/example_media/media_plugin_example.cpp create mode 100644 indra/plugins/filepicker/CMakeLists.txt create mode 100644 indra/plugins/filepicker/llfilepicker.cpp create mode 100644 indra/plugins/filepicker/llfilepicker.h rename indra/{media_plugins => plugins}/gstreamer010/CMakeLists.txt (82%) create mode 100755 indra/plugins/gstreamer010/llmediaimplgstreamer.h create mode 100755 indra/plugins/gstreamer010/llmediaimplgstreamertriviallogging.h rename indra/{media_plugins => plugins}/gstreamer010/llmediaimplgstreamervidplug.cpp (70%) mode change 100644 => 100755 rename indra/{media_plugins => plugins}/gstreamer010/llmediaimplgstreamervidplug.h (65%) mode change 100644 => 100755 rename indra/{media_plugins => plugins}/gstreamer010/media_plugin_gstreamer010.cpp (70%) mode change 100644 => 100755 rename indra/{media_plugins => plugins}/quicktime/CMakeLists.txt (97%) mode change 100644 => 100755 rename indra/{media_plugins => plugins}/quicktime/media_plugin_quicktime.cpp (95%) mode change 100644 => 100755 rename indra/{media_plugins => plugins}/webkit/CMakeLists.txt (88%) create mode 100644 indra/plugins/webkit/dummy_volume_catcher.cpp rename indra/{media_plugins => plugins}/webkit/linux_volume_catcher.cpp (90%) create mode 100755 indra/plugins/webkit/linux_volume_catcher.h rename indra/{media_plugins => plugins}/webkit/linux_volume_catcher_pa_syms.inc (100%) rename indra/{media_plugins => plugins}/webkit/linux_volume_catcher_paglib_syms.inc (100%) rename indra/{media_plugins => plugins}/webkit/mac_volume_catcher.cpp (85%) rename indra/{media_plugins => plugins}/webkit/media_plugin_webkit.cpp (93%) mode change 100644 => 100755 create mode 100644 indra/plugins/webkit/volume_catcher.h rename indra/{media_plugins => plugins}/webkit/windows_volume_catcher.cpp (61%) diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt deleted file mode 100644 index 9858d093e..000000000 --- a/indra/media_plugins/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# -*- cmake -*- - -add_subdirectory(base) - -add_subdirectory(webkit) - -if (LINUX) - add_subdirectory(gstreamer010) -endif (LINUX) - -if (DARWIN OR WINDOWS) - add_subdirectory(quicktime) -endif (DARWIN OR WINDOWS) - -add_subdirectory(example) diff --git a/indra/media_plugins/example/media_plugin_example.cpp b/indra/media_plugins/example/media_plugin_example.cpp deleted file mode 100644 index da7de0179..000000000 --- a/indra/media_plugins/example/media_plugin_example.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/** - * @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" - -#include "llgl.h" -#include "llplugininstance.h" -#include "llpluginmessage.h" -#include "llpluginmessageclasses.h" -#include "media_plugin_base.h" - -#include - -//////////////////////////////////////////////////////////////////////////////// -// -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; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -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; -} - -//////////////////////////////////////////////////////////////////////////////// -// -MediaPluginExample::~MediaPluginExample() -{ -} - -//////////////////////////////////////////////////////////////////////////////// -// -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; - }; - } -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginExample::write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ) -{ - // 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 ); -}; - -//////////////////////////////////////////////////////////////////////////////// -// -bool MediaPluginExample::init() -{ - LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" ); - message.setValue( "name", "Example 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 ) -{ - MediaPluginExample* self = new MediaPluginExample( host_send_func, host_user_data ); - *plugin_send_func = MediaPluginExample::staticReceiveMessage; - *plugin_user_data = ( void* )self; - - return 0; -} - diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h deleted file mode 100644 index 6bc272c00..000000000 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @file llmediaimplgstreamer.h - * @author Tofu Linden - * @brief implementation that supports media playback via GStreamer. - * - * @cond - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ - -// header guard -#ifndef llmediaimplgstreamer_h -#define llmediaimplgstreamer_h - -#if LL_GSTREAMER010_ENABLED - -extern "C" { -#include -#include - -#include "apr_pools.h" -#include "apr_dso.h" -} - - -extern "C" { -gboolean llmediaimplgstreamer_bus_callback (GstBus *bus, - GstMessage *message, - gpointer data); -} - -#endif // LL_GSTREAMER010_ENABLED - -#endif // llmediaimplgstreamer_h diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp deleted file mode 100644 index 2e4baaa9e..000000000 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/** - * @file llmediaimplgstreamer_syms.cpp - * @brief dynamic GStreamer symbol-grabbing code - * - * @cond - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ - -#if LL_GSTREAMER010_ENABLED - -#include - -extern "C" { -#include - -#include "apr_pools.h" -#include "apr_dso.h" -} - -#include "llmediaimplgstreamertriviallogging.h" - -#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) RTN (*ll##GSTSYM)(__VA_ARGS__) = NULL -#include "llmediaimplgstreamer_syms_raw.inc" -#include "llmediaimplgstreamer_syms_rawv.inc" -#undef LL_GST_SYM - -// a couple of stubs for disgusting reasons -GstDebugCategory* -ll_gst_debug_category_new(gchar *name, guint color, gchar *description) -{ - static GstDebugCategory dummy; - return &dummy; -} -void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname) -{ -} - -static bool sSymsGrabbed = false; -static apr_pool_t *sSymGSTDSOMemoryPool = NULL; -static apr_dso_handle_t *sSymGSTDSOHandleG = NULL; -static apr_dso_handle_t *sSymGSTDSOHandleV = NULL; - - -bool grab_gst_syms(std::string gst_dso_name, - std::string gst_dso_name_vid) -{ - if (sSymsGrabbed) - { - // already have grabbed good syms - return TRUE; - } - - bool sym_error = false; - bool rtn = false; - apr_status_t rv; - apr_dso_handle_t *sSymGSTDSOHandle = NULL; - -#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##GSTSYM, sSymGSTDSOHandle, #GSTSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #GSTSYM); if (REQ) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #GSTSYM, (void*)ll##GSTSYM);}while(0) - - //attempt to load the shared libraries - apr_pool_create(&sSymGSTDSOMemoryPool, NULL); - - if ( APR_SUCCESS == (rv = apr_dso_load(&sSymGSTDSOHandle, - gst_dso_name.c_str(), - sSymGSTDSOMemoryPool) )) - { - INFOMSG("Found DSO: %s", gst_dso_name.c_str()); -#include "llmediaimplgstreamer_syms_raw.inc" - - if ( sSymGSTDSOHandle ) - { - sSymGSTDSOHandleG = sSymGSTDSOHandle; - sSymGSTDSOHandle = NULL; - } - - if ( APR_SUCCESS == - (rv = apr_dso_load(&sSymGSTDSOHandle, - gst_dso_name_vid.c_str(), - sSymGSTDSOMemoryPool) )) - { - INFOMSG("Found DSO: %s", gst_dso_name_vid.c_str()); -#include "llmediaimplgstreamer_syms_rawv.inc" - rtn = !sym_error; - } - else - { - INFOMSG("Couldn't load DSO: %s", gst_dso_name_vid.c_str()); - rtn = false; // failure - } - } - else - { - INFOMSG("Couldn't load DSO: %s", gst_dso_name.c_str()); - rtn = false; // failure - } - - if (sym_error) - { - WARNMSG("Failed to find necessary symbols in GStreamer libraries."); - } - - if ( sSymGSTDSOHandle ) - { - sSymGSTDSOHandleV = sSymGSTDSOHandle; - sSymGSTDSOHandle = NULL; - } -#undef LL_GST_SYM - - sSymsGrabbed = !!rtn; - return rtn; -} - - -void ungrab_gst_syms() -{ - // should be safe to call regardless of whether we've - // actually grabbed syms. - - if ( sSymGSTDSOHandleG ) - { - apr_dso_unload(sSymGSTDSOHandleG); - sSymGSTDSOHandleG = NULL; - } - - if ( sSymGSTDSOHandleV ) - { - apr_dso_unload(sSymGSTDSOHandleV); - sSymGSTDSOHandleV = NULL; - } - - if ( sSymGSTDSOMemoryPool ) - { - apr_pool_destroy(sSymGSTDSOMemoryPool); - sSymGSTDSOMemoryPool = NULL; - } - - // NULL-out all of the symbols we'd grabbed -#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{ll##GSTSYM = NULL;}while(0) -#include "llmediaimplgstreamer_syms_raw.inc" -#include "llmediaimplgstreamer_syms_rawv.inc" -#undef LL_GST_SYM - - sSymsGrabbed = false; -} - - -#endif // LL_GSTREAMER010_ENABLED diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h deleted file mode 100644 index d1559089c..000000000 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @file llmediaimplgstreamer_syms.h - * @brief dynamic GStreamer symbol-grabbing code - * - * @cond - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ - -#include "linden_common.h" - -#if LL_GSTREAMER010_ENABLED - -extern "C" { -#include -} - -bool grab_gst_syms(std::string gst_dso_name, - std::string gst_dso_name_vid); -void ungrab_gst_syms(); - -#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) extern RTN (*ll##GSTSYM)(__VA_ARGS__) -#include "llmediaimplgstreamer_syms_raw.inc" -#include "llmediaimplgstreamer_syms_rawv.inc" -#undef LL_GST_SYM - -// regrettable hacks to give us better runtime compatibility with older systems -#define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0) -#define llg_return_val_if_fail(COND,V) do{if (!(COND)) return V;}while(0) - -// regrettable hacks because GStreamer was not designed for runtime loading -#undef GST_TYPE_MESSAGE -#define GST_TYPE_MESSAGE (llgst_message_get_type()) -#undef GST_TYPE_OBJECT -#define GST_TYPE_OBJECT (llgst_object_get_type()) -#undef GST_TYPE_PIPELINE -#define GST_TYPE_PIPELINE (llgst_pipeline_get_type()) -#undef GST_TYPE_ELEMENT -#define GST_TYPE_ELEMENT (llgst_element_get_type()) -#undef GST_TYPE_VIDEO_SINK -#define GST_TYPE_VIDEO_SINK (llgst_video_sink_get_type()) -// more regrettable hacks to stub-out these .h-exposed GStreamer internals -void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname); -#undef _gst_debug_register_funcptr -#define _gst_debug_register_funcptr ll_gst_debug_register_funcptr -GstDebugCategory* ll_gst_debug_category_new(gchar *name, guint color, gchar *description); -#undef _gst_debug_category_new -#define _gst_debug_category_new ll_gst_debug_category_new -#undef __gst_debug_enabled -#define __gst_debug_enabled (0) - -// more hacks -#define LLGST_MESSAGE_TYPE_NAME(M) (llgst_message_type_get_name(GST_MESSAGE_TYPE(M))) - -#endif // LL_GSTREAMER010_ENABLED diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc deleted file mode 100644 index b33e59363..000000000 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc +++ /dev/null @@ -1,51 +0,0 @@ - -// required symbols to grab -LL_GST_SYM(true, gst_pad_peer_accept_caps, gboolean, GstPad *pad, GstCaps *caps); -LL_GST_SYM(true, gst_buffer_new, GstBuffer*, void); -LL_GST_SYM(true, gst_buffer_set_caps, void, GstBuffer*, GstCaps *); -LL_GST_SYM(true, gst_structure_set_value, void, GstStructure *, const gchar *, const GValue*); -LL_GST_SYM(true, gst_init_check, gboolean, int *argc, char **argv[], GError ** err); -LL_GST_SYM(true, gst_message_get_type, GType, void); -LL_GST_SYM(true, gst_message_type_get_name, const gchar*, GstMessageType type); -LL_GST_SYM(true, gst_message_parse_error, void, GstMessage *message, GError **gerror, gchar **debug); -LL_GST_SYM(true, gst_message_parse_warning, void, GstMessage *message, GError **gerror, gchar **debug); -LL_GST_SYM(true, gst_message_parse_state_changed, void, GstMessage *message, GstState *oldstate, GstState *newstate, GstState *pending); -LL_GST_SYM(true, gst_element_set_state, GstStateChangeReturn, GstElement *element, GstState state); -LL_GST_SYM(true, gst_object_unref, void, gpointer object); -LL_GST_SYM(true, gst_object_get_type, GType, void); -LL_GST_SYM(true, gst_pipeline_get_type, GType, void); -LL_GST_SYM(true, gst_pipeline_get_bus, GstBus*, GstPipeline *pipeline); -LL_GST_SYM(true, gst_bus_add_watch, guint, GstBus * bus, GstBusFunc func, gpointer user_data); -LL_GST_SYM(true, gst_element_factory_make, GstElement*, const gchar *factoryname, const gchar *name); -LL_GST_SYM(true, gst_element_get_type, GType, void); -LL_GST_SYM(true, gst_static_pad_template_get, GstPadTemplate*, GstStaticPadTemplate *pad_template); -LL_GST_SYM(true, gst_element_class_add_pad_template, void, GstElementClass *klass, GstPadTemplate *temp); -LL_GST_SYM(true, gst_element_class_set_details, void, GstElementClass *klass, const GstElementDetails *details); -LL_GST_SYM(true, gst_caps_unref, void, GstCaps* caps); -LL_GST_SYM(true, gst_caps_ref, GstCaps *, GstCaps* caps); -//LL_GST_SYM(true, gst_caps_is_empty, gboolean, const GstCaps *caps); -LL_GST_SYM(true, gst_caps_from_string, GstCaps *, const gchar *string); -LL_GST_SYM(true, gst_caps_replace, void, GstCaps **caps, GstCaps *newcaps); -LL_GST_SYM(true, gst_caps_get_structure, GstStructure *, const GstCaps *caps, guint index); -LL_GST_SYM(true, gst_caps_copy, GstCaps *, const GstCaps * caps); -//LL_GST_SYM(true, gst_caps_intersect, GstCaps *, const GstCaps *caps1, const GstCaps *caps2); -LL_GST_SYM(true, gst_element_register, gboolean, GstPlugin *plugin, const gchar *name, guint rank, GType type); -LL_GST_SYM(true, _gst_plugin_register_static, void, GstPluginDesc *desc); -LL_GST_SYM(true, gst_structure_get_int, gboolean, const GstStructure *structure, const gchar *fieldname, gint *value); -LL_GST_SYM(true, gst_structure_get_value, G_CONST_RETURN GValue *, const GstStructure *structure, const gchar *fieldname); -LL_GST_SYM(true, gst_value_get_fraction_numerator, gint, const GValue *value); -LL_GST_SYM(true, gst_value_get_fraction_denominator, gint, const GValue *value); -LL_GST_SYM(true, gst_structure_get_name, G_CONST_RETURN gchar *, const GstStructure *structure); -LL_GST_SYM(true, gst_element_seek, bool, GstElement *, gdouble, GstFormat, GstSeekFlags, GstSeekType, gint64, GstSeekType, gint64); - -// optional symbols to grab -LL_GST_SYM(false, gst_registry_fork_set_enabled, void, gboolean enabled); -LL_GST_SYM(false, gst_segtrap_set_enabled, void, gboolean enabled); -LL_GST_SYM(false, gst_message_parse_buffering, void, GstMessage *message, gint *percent); -LL_GST_SYM(false, gst_message_parse_info, void, GstMessage *message, GError **gerror, gchar **debug); -LL_GST_SYM(false, gst_element_query_position, gboolean, GstElement *element, GstFormat *format, gint64 *cur); -LL_GST_SYM(false, gst_version, void, guint *major, guint *minor, guint *micro, guint *nano); - -// GStreamer 'internal' symbols which may not be visible in some runtimes but are still used in expanded GStreamer header macros - yuck! We'll substitute our own stubs for these. -//LL_GST_SYM(true, _gst_debug_register_funcptr, void, GstDebugFuncPtr func, gchar* ptrname); -//LL_GST_SYM(true, _gst_debug_category_new, GstDebugCategory *, gchar *name, guint color, gchar *description); diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc deleted file mode 100644 index 14fbcb48b..000000000 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc +++ /dev/null @@ -1,5 +0,0 @@ - -// required symbols to grab -LL_GST_SYM(true, gst_video_sink_get_type, GType, void); - -// optional symbols to grab diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h deleted file mode 100644 index e7b31bec9..000000000 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @file llmediaimplgstreamertriviallogging.h - * @brief minimal logging utilities. - * - * @cond - * $LicenseInfo:firstyear=2009&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 - */ - -#ifndef __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__ -#define __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__ - -#include - -extern "C" { -#include -#include -} - -///////////////////////////////////////////////////////////////////////// -// Debug/Info/Warning macros. -#define MSGMODULEFOO "(media plugin)" -#define STDERRMSG(...) do{\ - fprintf(stderr, " pid:%d: ", (int)getpid());\ - fprintf(stderr, MSGMODULEFOO " %s:%d: ", __FUNCTION__, __LINE__);\ - fprintf(stderr, __VA_ARGS__);\ - fputc('\n',stderr);\ - }while(0) -#define NULLMSG(...) do{}while(0) - -#define DEBUGMSG NULLMSG -#define INFOMSG STDERRMSG -#define WARNMSG STDERRMSG -///////////////////////////////////////////////////////////////////////// - -#endif /* __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__ */ diff --git a/indra/media_plugins/webkit/dummy_volume_catcher.cpp b/indra/media_plugins/webkit/dummy_volume_catcher.cpp deleted file mode 100644 index d54b31b2a..000000000 --- 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/volume_catcher.h b/indra/media_plugins/webkit/volume_catcher.h deleted file mode 100644 index 337f2913d..000000000 --- a/indra/media_plugins/webkit/volume_catcher.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @file volume_catcher.h - * @brief Interface to a class with platform-specific implementations that allows control of the audio volume of all sources in the current process. - * - * @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 - */ - -#ifndef VOLUME_CATCHER_H -#define VOLUME_CATCHER_H - -#include "linden_common.h" - -class VolumeCatcherImpl; - -class VolumeCatcher -{ - public: - VolumeCatcher(); - ~VolumeCatcher(); - - void setVolume(F32 volume); // 0.0 - 1.0 - - // Set the left-right pan of audio sources - // where -1.0 = left, 0 = center, and 1.0 = right - void setPan(F32 pan); - - void pump(); // call this at least a few times a second if you can - it affects how quickly we can 'catch' a new audio source and adjust its volume - - private: - VolumeCatcherImpl *pimpl; -}; - -#endif // VOLUME_CATCHER_H diff --git a/indra/plugins/CMakeLists.txt b/indra/plugins/CMakeLists.txt new file mode 100644 index 000000000..de57249ba --- /dev/null +++ b/indra/plugins/CMakeLists.txt @@ -0,0 +1,17 @@ +# -*- cmake -*- + +add_subdirectory(base_basic) +add_subdirectory(base_media) +add_subdirectory(filepicker) +add_subdirectory(webkit) + +if (LINUX) + add_subdirectory(gstreamer010) +endif (LINUX) + +if (WINDOWS OR DARWIN) + add_subdirectory(quicktime) +endif (WINDOWS OR DARWIN) + +add_subdirectory(example_basic) +add_subdirectory(example_media) diff --git a/indra/plugins/base_basic/CMakeLists.txt b/indra/plugins/base_basic/CMakeLists.txt new file mode 100644 index 000000000..1ff52fda5 --- /dev/null +++ b/indra/plugins/base_basic/CMakeLists.txt @@ -0,0 +1,39 @@ +# -*- cmake -*- + +project(basic_plugin_base) + +include(00-Common) +include(LLCommon) +include(LLPlugin) +include(Linking) +include(PluginAPI) + +include_directories( + ${LLPLUGIN_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} +) + +### basic_plugin_base + +if(NOT CMAKE_SIZEOF_VOID_P MATCHES 4) + if(WINDOWS) + add_definitions(/FIXED:NO) + else(WINDOWS) # not windows therefore gcc LINUX and DARWIN + add_definitions(-fPIC) + endif(WINDOWS) +endif (NOT CMAKE_SIZEOF_VOID_P MATCHES 4) + +set(basic_plugin_base_SOURCE_FILES + basic_plugin_base.cpp +) + +set(basic_plugin_base_HEADER_FILES + CMakeLists.txt + + basic_plugin_base.h +) + +add_library(basic_plugin_base + ${basic_plugin_base_SOURCE_FILES} +) + diff --git a/indra/plugins/base_basic/basic_plugin_base.cpp b/indra/plugins/base_basic/basic_plugin_base.cpp new file mode 100755 index 000000000..90b5964ef --- /dev/null +++ b/indra/plugins/base_basic/basic_plugin_base.cpp @@ -0,0 +1,136 @@ +/** + * @file basic_plugin_base.cpp + * @brief Basic plugin base class for Basic API plugin system + * + * All plugins should be a subclass of BasicPluginBase. + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +#include "linden_common.h" +#include "basic_plugin_base.h" + + +// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint + +//////////////////////////////////////////////////////////////////////////////// +/// Basic plugin constructor. +/// +/// @param[in] send_message_function Function for sending messages from plugin to plugin loader shell +/// @param[in] plugin_instance Message data for messages from plugin to plugin loader shell +BasicPluginBase::BasicPluginBase(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance) +{ + mSendMessageFunction = send_message_function; + mPluginInstance = plugin_instance; +} + +/** + * Receive message from plugin loader shell. + * + * @param[in] message_string Message string + * @param[in] user_data Message data + * + */ +void BasicPluginBase::staticReceiveMessage(char const* message_string, BasicPluginBase** self_ptr) +{ + BasicPluginBase* self = *self_ptr; + if(self != NULL) + { + self->receiveMessage(message_string); + + // If the plugin has processed the delete message, delete it. + if(self->mDeleteMe) + { + delete self; + *self_ptr = NULL; + } + } +} + +// This is the SLPlugin process. +// This is the loaded DSO. +// +// Call this function to send 'message' to the viewer. +/** + * Send message to plugin loader shell. + * + * @param[in] message Message data being sent to plugin loader shell + * + */ +void BasicPluginBase::sendMessage(const LLPluginMessage &message) +{ + std::string output = message.generate(); + mSendMessageFunction(output.c_str(), &mPluginInstance); +} + +#if LL_WINDOWS +# define LLSYMEXPORT __declspec(dllexport) +#elif LL_LINUX +# define LLSYMEXPORT __attribute__ ((visibility("default"))) +#else +# define LLSYMEXPORT /**/ +#endif + +extern "C" +{ + LLSYMEXPORT int LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction send_message_function, + LLPluginInstance* plugin_instance, + LLPluginInstance::receiveMessageFunction* receive_message_function, + BasicPluginBase** plugin_object); +} + +/** + * Plugin initialization and entry point. Establishes communication channel for messages between plugin and plugin loader shell. TODO:DOC - Please check! + * + * @param[in] send_message_function Function for sending messages from plugin to viewer + * @param[in] plugin_instance Message data for messages from plugin to plugin loader shell + * @param[out] receive_message_function Function for receiving message from viewer to plugin + * @param[out] plugin_object Pointer to plugin instance + * + * @return int, where 0=success + * + */ +LLSYMEXPORT int +LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction send_message_function, + LLPluginInstance* plugin_instance, + LLPluginInstance::receiveMessageFunction* receive_message_function, + BasicPluginBase** plugin_object) +{ + *receive_message_function = BasicPluginBase::staticReceiveMessage; + return create_plugin(send_message_function, plugin_instance, plugin_object); +} + +#ifdef WIN32 +int WINAPI DllEntryPoint( HINSTANCE hInstance, unsigned long reason, void* params ) +{ + return 1; +} +#endif diff --git a/indra/media_plugins/base/media_plugin_base.exp b/indra/plugins/base_basic/basic_plugin_base.exp old mode 100755 new mode 100644 similarity index 100% rename from indra/media_plugins/base/media_plugin_base.exp rename to indra/plugins/base_basic/basic_plugin_base.exp diff --git a/indra/plugins/base_basic/basic_plugin_base.h b/indra/plugins/base_basic/basic_plugin_base.h new file mode 100755 index 000000000..bbabb18b7 --- /dev/null +++ b/indra/plugins/base_basic/basic_plugin_base.h @@ -0,0 +1,88 @@ +/** + * @file basic_plugin_base.h + * @brief Basic plugin base class for Basic API plugin system + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +#ifndef BASIC_PLUGIN_BASE_H +#define BASIC_PLUGIN_BASE_H + +#include + +#include "linden_common.h" + +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" + +class BasicPluginBase +{ +public: + BasicPluginBase(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance); + //! Basic plugin destructor. + virtual ~BasicPluginBase() {} + + //! Handle received message from plugin loader shell. + virtual void receiveMessage(char const* message_string) = 0; + + // This function is actually called and then calls the member function above. + static void staticReceiveMessage(char const* message_string, BasicPluginBase** self_ptr); + +protected: + void sendMessage(LLPluginMessage const& message); + + //! Message data being sent to plugin loader shell by mSendMessageFunction. + LLPluginInstance* mPluginInstance; + + //! Function to send message from plugin to plugin loader shell. + LLPluginInstance::sendMessageFunction mSendMessageFunction; + + //! Flag to delete plugin instance (self). + bool mDeleteMe; +}; + +/** The plugin must define this function to create its instance. + * It should look something like this: + * @code + * { + * *plugin_object = new FooPluginBar(send_message_function, plugin_instance); + * return 0; + * } + * @endcode + */ +int create_plugin( + LLPluginInstance::sendMessageFunction send_message_function, + LLPluginInstance* plugin_instance, + BasicPluginBase** plugin_object); + +#endif // BASIC_PLUGIN_BASE + diff --git a/indra/media_plugins/base/CMakeLists.txt b/indra/plugins/base_media/CMakeLists.txt similarity index 81% rename from indra/media_plugins/base/CMakeLists.txt rename to indra/plugins/base_media/CMakeLists.txt index 8d620433a..f2c8d7225 100644 --- a/indra/media_plugins/base/CMakeLists.txt +++ b/indra/plugins/base_media/CMakeLists.txt @@ -12,6 +12,7 @@ include(LLWindow) include(Linking) include(PluginAPI) include(FindOpenGL) +include(BasicPluginBase) include_directories( ${LLPLUGIN_INCLUDE_DIRS} @@ -20,9 +21,9 @@ include_directories( ${LLIMAGE_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} + ${BASIC_PLUGIN_BASE_INCLUDE_DIRS} ) - ### media_plugin_base if(NOT CMAKE_SIZEOF_VOID_P MATCHES 4) @@ -47,3 +48,11 @@ add_library(media_plugin_base ${media_plugin_base_SOURCE_FILES} ) +target_link_libraries(media_plugin_base + ${BASIC_PLUGIN_BASE_LIBRARIES} +) + +add_dependencies(media_plugin_base + ${BASIC_PLUGIN_BASE_LIBRARIES} +) + diff --git a/indra/media_plugins/base/media_plugin_base.cpp b/indra/plugins/base_media/media_plugin_base.cpp old mode 100644 new mode 100755 similarity index 66% rename from indra/media_plugins/base/media_plugin_base.cpp rename to indra/plugins/base_media/media_plugin_base.cpp index 47acdfd28..102d18996 --- a/indra/media_plugins/base/media_plugin_base.cpp +++ b/indra/plugins/base_media/media_plugin_base.cpp @@ -40,18 +40,15 @@ // TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint + //////////////////////////////////////////////////////////////////////////////// /// Media plugin constructor. /// -/// @param[in] host_send_func Function for sending messages from plugin to plugin loader shell +/// @param[in] send_message_function Function for sending messages from plugin to plugin loader shell /// @param[in] host_user_data Message data for messages from plugin to plugin loader shell - -MediaPluginBase::MediaPluginBase( - LLPluginInstance::sendMessageFunction host_send_func, - void *host_user_data ) +MediaPluginBase::MediaPluginBase(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance) + : BasicPluginBase(send_message_function, plugin_instance) { - mHostSendFunction = host_send_func; - mHostUserData = host_user_data; mDeleteMe = false; mPixels = 0; mWidth = 0; @@ -103,43 +100,6 @@ void MediaPluginBase::setStatus(EStatus status) } } - -/** - * Receive message from plugin loader shell. - * - * @param[in] message_string Message string - * @param[in] user_data Message data - * - */ -void MediaPluginBase::staticReceiveMessage(const char *message_string, void **user_data) -{ - MediaPluginBase *self = (MediaPluginBase*)*user_data; - - if(self != NULL) - { - self->receiveMessage(message_string); - - // If the plugin has processed the delete message, delete it. - if(self->mDeleteMe) - { - delete self; - *user_data = NULL; - } - } -} - -/** - * Send message to plugin loader shell. - * - * @param[in] message Message data being sent to plugin loader shell - * - */ -void MediaPluginBase::sendMessage(const LLPluginMessage &message) -{ - std::string output = message.generate(); - mHostSendFunction(output.c_str(), &mHostUserData); -} - /** * Notifies plugin loader shell that part of display area needs to be redrawn. * @@ -183,28 +143,6 @@ void MediaPluginBase::sendStatus() # define LLSYMEXPORT /**/ #endif -extern "C" -{ - LLSYMEXPORT int LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data); -} - -/** - * Plugin initialization and entry point. Establishes communication channel for messages between plugin and plugin loader shell. TODO:DOC - Please check! - * - * @param[in] host_send_func Function for sending messages from plugin to plugin loader shell - * @param[in] host_user_data Message data for messages from plugin to plugin loader shell - * @param[out] plugin_send_func Function for plugin to receive messages from plugin loader shell - * @param[out] plugin_user_data Pointer to plugin instance - * - * @return int, where 0=success - * - */ -LLSYMEXPORT int -LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) -{ - return init_media_plugin(host_send_func, host_user_data, plugin_send_func, plugin_user_data); -} - #ifdef WIN32 int WINAPI DllEntryPoint( HINSTANCE hInstance, unsigned long reason, void* params ) { diff --git a/indra/plugins/base_media/media_plugin_base.exp b/indra/plugins/base_media/media_plugin_base.exp new file mode 100755 index 000000000..d8c7bb712 --- /dev/null +++ b/indra/plugins/base_media/media_plugin_base.exp @@ -0,0 +1,2 @@ +_LLPluginInitEntryPoint + diff --git a/indra/media_plugins/base/media_plugin_base.h b/indra/plugins/base_media/media_plugin_base.h old mode 100644 new mode 100755 similarity index 67% rename from indra/media_plugins/base/media_plugin_base.h rename to indra/plugins/base_media/media_plugin_base.h index efb0629a5..5aebbe1a0 --- a/indra/media_plugins/base/media_plugin_base.h +++ b/indra/plugins/base_media/media_plugin_base.h @@ -33,27 +33,17 @@ * @endcond */ -#include "linden_common.h" +#ifndef MEDIA_PLUGIN_BASE_H +#define MEDIA_PLUGIN_BASE_H -#include "llplugininstance.h" -#include "llpluginmessage.h" -#include "llpluginmessageclasses.h" +#include "basic_plugin_base.h" - -class MediaPluginBase +class MediaPluginBase : public BasicPluginBase { public: - MediaPluginBase(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); - /** Media plugin destructor. */ - virtual ~MediaPluginBase() {} - - /** Handle received message from plugin loader shell. */ - virtual void receiveMessage(const char *message_string) = 0; - - static void staticReceiveMessage(const char *message_string, void **user_data); + MediaPluginBase(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance); protected: - /** Plugin status. */ typedef enum { @@ -76,7 +66,6 @@ protected: size_t mSize; }; - void sendMessage(const LLPluginMessage &message); void sendStatus(); std::string statusString(); void setStatus(EStatus status); @@ -87,13 +76,6 @@ protected: /** Map of shared memory names to shared memory. */ typedef std::map SharedSegmentMap; - - /** Function to send message from plugin to plugin loader shell. */ - LLPluginInstance::sendMessageFunction mHostSendFunction; - /** Message data being sent to plugin loader shell by mHostSendFunction. */ - void *mHostUserData; - /** Flag to delete plugin instance (self). */ - bool mDeleteMe; /** Pixel array to display. TODO:DOC are pixels always 24-bit RGB format, aligned on 32-bit boundary? Also: calling this a pixel array may be misleading since 1 pixel > 1 char. */ unsigned char* mPixels; /** TODO:DOC what's this for -- does a texture have its own piece of shared memory? updated on size_change_request, cleared on shm_remove */ @@ -115,22 +97,4 @@ protected: }; -/** The plugin must define this function to create its instance. - * It should look something like this: - * @code - * { - * MediaPluginFoo *self = new MediaPluginFoo(host_send_func, host_user_data); - * *plugin_send_func = MediaPluginFoo::staticReceiveMessage; - * *plugin_user_data = (void*)self; - * - * return 0; - * } - * @endcode - */ -int init_media_plugin( - LLPluginInstance::sendMessageFunction host_send_func, - void *host_user_data, - LLPluginInstance::sendMessageFunction *plugin_send_func, - void **plugin_user_data); - - +#endif // MEDIA_PLUGIN_BASE_H diff --git a/indra/plugins/example_basic/CMakeLists.txt b/indra/plugins/example_basic/CMakeLists.txt new file mode 100644 index 000000000..fdc71a60c --- /dev/null +++ b/indra/plugins/example_basic/CMakeLists.txt @@ -0,0 +1,68 @@ +# -*- cmake -*- + +project(basic_plugin_example) + +include(00-Common) +include(LLCommon) +include(LLPlugin) +include(Linking) +include(PluginAPI) +include(BasicPluginBase) + +include_directories( + ${LLPLUGIN_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${BASIC_PLUGIN_BASE_INCLUDE_DIRS} +) + +### basic_plugin_example + +if(NOT CMAKE_SIZEOF_VOID_P MATCHES 4) + if(WINDOWS) + add_definitions(/FIXED:NO) + else(WINDOWS) # not windows therefore gcc LINUX and DARWIN + add_definitions(-fPIC) + endif(WINDOWS) +endif (NOT CMAKE_SIZEOF_VOID_P MATCHES 4) + +set(basic_plugin_example_SOURCE_FILES + basic_plugin_example.cpp + ) + +add_library(basic_plugin_example + SHARED + ${basic_plugin_example_SOURCE_FILES} +) + +target_link_libraries(basic_plugin_example + ${LLPLUGIN_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${BASIC_PLUGIN_BASE_LIBRARIES} +) + +add_dependencies(basic_plugin_example + ${LLPLUGIN_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${BASIC_PLUGIN_BASE_LIBRARIES} +) + +if (WINDOWS) + set_target_properties( + basic_plugin_example + PROPERTIES + LINK_FLAGS "/MANIFEST:NO" + ) +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( + basic_plugin_example + PROPERTIES + PREFIX "" + BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path" + LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base_basic/basic_plugin_base.exp" + ) + +endif (DARWIN) diff --git a/indra/plugins/example_basic/basic_plugin_example.cpp b/indra/plugins/example_basic/basic_plugin_example.cpp new file mode 100644 index 000000000..a6a255276 --- /dev/null +++ b/indra/plugins/example_basic/basic_plugin_example.cpp @@ -0,0 +1,123 @@ +/** + * @file basic_plugin_example.cpp + * @brief Example Plugin for a basic plugin. + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +#include "linden_common.h" +#include "basic_plugin_base.h" + +class BasicPluginExample : public BasicPluginBase +{ + public: + BasicPluginExample(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance); + ~BasicPluginExample(); + + /*virtual*/ void receiveMessage(char const* message_string); + + private: + bool init(); +}; + +BasicPluginExample::BasicPluginExample(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance) : + BasicPluginBase(send_message_function, plugin_instance) +{ +} + +BasicPluginExample::~BasicPluginExample() +{ +} + +void BasicPluginExample::receiveMessage(char const* message_string) +{ + LLPluginMessage message_in; + + if (message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + + if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if (message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_BASIC] = LLPLUGIN_MESSAGE_CLASS_BASIC_VERSION; + message.setValueLLSD("versions", versions); + + std::string plugin_version = "Basic Plugin Example, version 1.0.0.0"; + message.setValue("plugin_version", plugin_version); + sendMessage(message); + } + else if (message_name == "idle") + { + // This whole message should not have existed imho -- Aleric + } + else + { + std::cerr << "BasicPluginExample::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else if (message_class == LLPLUGIN_MESSAGE_CLASS_BASIC) + { + if (message_name == "poke") + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_BASIC, "pokeback"); + sendMessage(message); + } + } + else + { + std::cerr << "BasicPluginExample::receiveMessage: unknown message class: " << message_class << std::endl; + } + } +} + +bool BasicPluginExample::init(void) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_BASIC, "name_text"); + message.setValue("name", "Basic Plugin Example"); + sendMessage(message); + + return true; +} + +int create_plugin(LLPluginInstance::sendMessageFunction send_message_function, + LLPluginInstance* plugin_instance, + BasicPluginBase** plugin_object) +{ + *plugin_object = new BasicPluginExample(send_message_function, plugin_instance); + return 0; +} + diff --git a/indra/media_plugins/example/CMakeLists.txt b/indra/plugins/example_media/CMakeLists.txt similarity index 83% rename from indra/media_plugins/example/CMakeLists.txt rename to indra/plugins/example_media/CMakeLists.txt index 54dc5de1e..99859ae8a 100644 --- a/indra/media_plugins/example/CMakeLists.txt +++ b/indra/plugins/example_media/CMakeLists.txt @@ -14,7 +14,7 @@ include(PluginAPI) include(MediaPluginBase) include(FindOpenGL) -include(ExamplePlugin) +#include(ExamplePlugin) include_directories( ${LLPLUGIN_INCLUDE_DIRS} @@ -26,16 +26,15 @@ include_directories( ${LLWINDOW_INCLUDE_DIRS} ) - ### media_plugin_example -if(NOT WORD_SIZE EQUAL 32) - if(WINDOWS) - add_definitions(/FIXED:NO) - else(WINDOWS) # not windows therefore gcc LINUX and DARWIN - add_definitions(-fPIC) - endif(WINDOWS) -endif(NOT WORD_SIZE EQUAL 32) +if(NOT CMAKE_SIZEOF_VOID_P MATCHES 4) + if(WINDOWS) + add_definitions(/FIXED:NO) + else(WINDOWS) # not windows therefore gcc LINUX and DARWIN + add_definitions(-fPIC) + endif(WINDOWS) +endif (NOT CMAKE_SIZEOF_VOID_P MATCHES 4) set(media_plugin_example_SOURCE_FILES media_plugin_example.cpp @@ -76,7 +75,7 @@ if (DARWIN) PREFIX "" BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@executable_path" - LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp" + LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base_media/media_plugin_base.exp" ) endif (DARWIN) diff --git a/indra/plugins/example_media/media_plugin_example.cpp b/indra/plugins/example_media/media_plugin_example.cpp new file mode 100755 index 000000000..bdb77fb6e --- /dev/null +++ b/indra/plugins/example_media/media_plugin_example.cpp @@ -0,0 +1,490 @@ +/** + * @file media_plugin_example.cpp + * @brief Example plugin for LLMedia API plugin system + * + * @cond + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +#include "linden_common.h" + +#include "llgl.h" +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#include + +//////////////////////////////////////////////////////////////////////////////// +// +class MediaPluginExample : + public MediaPluginBase +{ + public: + MediaPluginExample(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance); + ~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; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +MediaPluginExample::MediaPluginExample(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance) : + MediaPluginBase(send_message_function, plugin_instance) +{ + mFirstTime = true; + mWidth = 0; + mHeight = 0; + mDepth = 4; + mPixels = 0; + mMouseButtonDown = false; + mStopAction = false; + mLastUpdateTime = 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// +MediaPluginExample::~MediaPluginExample() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginExample::receiveMessage( const char* message_string ) +{ + LLPluginMessage message_in; + + if ( message_in.parse( message_string ) >= 0 ) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + + if ( message_class == LLPLUGIN_MESSAGE_CLASS_BASE ) + { + if ( message_name == "init" ) + { + LLPluginMessage message( "base", "init_response" ); + LLSD versions = LLSD::emptyMap(); + versions[ LLPLUGIN_MESSAGE_CLASS_BASE ] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; + message.setValueLLSD( "versions", versions ); + + std::string plugin_version = "Example media plugin, Example Version 1.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( time ); + } + else + if ( message_name == "cleanup" ) + { + // clean up here + } + 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 << "MediaPluginExample::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 << "MediaPluginExample::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. + LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params" ); + message.setValueS32( "default_width", mWidth ); + message.setValueS32( "default_height", mHeight ); + message.setValueS32( "depth", mDepth ); + message.setValueU32( "internalformat", GL_RGBA ); + message.setValueU32( "format", GL_RGBA ); + message.setValueU32( "type", GL_UNSIGNED_BYTE ); + message.setValueBoolean( "coords_opengl", false ); + 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; + + init(); + }; + }; + + 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" ); + if ( ! uri.empty() ) + { + }; + } + else + if ( message_name == "mouse_event" ) + { + std::string event = message_in.getValue( "event" ); + S32 button = message_in.getValueS32( "button" ); + + // left mouse button + if ( button == 0 ) + { + int mouse_x = message_in.getValueS32( "x" ); + int mouse_y = message_in.getValueS32( "y" ); + std::string modifiers = message_in.getValue( "modifiers" ); + + if ( event == "move" ) + { + if ( mMouseButtonDown ) + write_pixel( mouse_x, mouse_y, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80 ); + } + else + if ( event == "down" ) + { + mMouseButtonDown = true; + } + else + if ( event == "up" ) + { + mMouseButtonDown = false; + } + else + if ( event == "double_click" ) + { + }; + }; + } + 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" ); + + if ( event == "down" ) + { + if ( key == ' ') + { + mLastUpdateTime = 0; + update( 0.0f ); + }; + }; + } + else + { + //std::cerr << "MediaPluginExample::receiveMessage: unknown media message: " << message_string << std::endl; + }; + } + else + if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER ) + { + if ( message_name == "browse_reload" ) + { + mLastUpdateTime = 0; + mFirstTime = true; + mStopAction = false; + update( 0.0f ); + } + else + if ( message_name == "browse_stop" ) + { + for( int n = 0; n < ENumObjects; ++n ) + mXInc[ n ] = mYInc[ n ] = 0; + + mStopAction = true; + update( 0.0f ); + } + else + { + //std::cerr << "MediaPluginExample::receiveMessage: unknown media_browser message: " << message_string << std::endl; + }; + } + else + { + //std::cerr << "MediaPluginExample::receiveMessage: unknown message class: " << message_class << std::endl; + }; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginExample::write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ) +{ + // 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 ); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +bool MediaPluginExample::init() +{ + LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" ); + message.setValue( "name", "Example Plugin" ); + sendMessage( message ); + + return true; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +int create_plugin(LLPluginInstance::sendMessageFunction send_message_function, + LLPluginInstance* plugin_instance, + BasicPluginBase** plugin_object) +{ + *plugin_object = new MediaPluginExample(send_message_function, plugin_instance); + return 0; +} diff --git a/indra/plugins/filepicker/CMakeLists.txt b/indra/plugins/filepicker/CMakeLists.txt new file mode 100644 index 000000000..cea18360a --- /dev/null +++ b/indra/plugins/filepicker/CMakeLists.txt @@ -0,0 +1,81 @@ +# -*- cmake -*- + +project(basic_plugin_filepicker) + +include(00-Common) +include(LLCommon) +include(LLPlugin) +include(Linking) +include(PluginAPI) +include(BasicPluginBase) +include(UI) + +include_directories( + ${LLPLUGIN_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${BASIC_PLUGIN_BASE_INCLUDE_DIRS} + ${LLUI_INCLUDE_DIRS} +) + +### basic_plugin_filepicker + +if(NOT CMAKE_SIZEOF_VOID_P MATCHES 4) + if(WINDOWS) + add_definitions(/FIXED:NO) + else(WINDOWS) # not windows therefore gcc LINUX and DARWIN + add_definitions(-fPIC) + endif(WINDOWS) +endif (NOT CMAKE_SIZEOF_VOID_P MATCHES 4) + +set(basic_plugin_filepicker_SOURCE_FILES + basic_plugin_filepicker.cpp + llfilepicker.cpp + ) + +set(basic_plugin_filepicker_HEADER_FILES + llfilepicker.h + ) + +set_source_files_properties(${basic_plugin_filepicker_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +list(APPEND basic_plugin_filepicker_SOURCE_FILES ${basic_plugin_filepicker_HEADER_FILES}) + +add_library(basic_plugin_filepicker + SHARED + ${basic_plugin_filepicker_SOURCE_FILES} +) + +target_link_libraries(basic_plugin_filepicker + ${LLPLUGIN_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${BASIC_PLUGIN_BASE_LIBRARIES} + ${UI_LIBRARIES} +) + +add_dependencies(basic_plugin_filepicker + ${LLPLUGIN_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${BASIC_PLUGIN_BASE_LIBRARIES} +) + +if (WINDOWS) + set_target_properties( + basic_plugin_filepicker + PROPERTIES + LINK_FLAGS "/MANIFEST:NO" + ) +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( + basic_plugin_filepicker + PROPERTIES + PREFIX "" + BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path" + LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base_basic/basic_plugin_base.exp" + ) + +endif (DARWIN) diff --git a/indra/plugins/filepicker/llfilepicker.cpp b/indra/plugins/filepicker/llfilepicker.cpp new file mode 100644 index 000000000..f9a3ab8c1 --- /dev/null +++ b/indra/plugins/filepicker/llfilepicker.cpp @@ -0,0 +1,1414 @@ +/** + * @file llfilepicker.cpp + * @brief OS-specific file picker + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llfilepicker.h" +#include "llpreprocessor.h" +#include "llerror.h" +#include "basic_plugin_base.h" // For PLS_INFOS etc. + +#if LL_SDL +#include "llwindowsdl.h" // for some X/GTK utils to help with filepickers +#endif // LL_SDL + +// Translation map. +typedef std::map translation_map_type; +translation_map_type translation_map; + +// A temporary hack to minimize the number of changes from the original llfilepicker.cpp. +#define LLTrans translation +namespace translation +{ + std::string getString(char const* key) + { + translation_map_type::iterator iter = translation_map.find(key); + return (iter != translation_map.end()) ? iter->second : key; + } + + void add(std::string const& key, std::string const& translation) + { + PLS_INFOS << "Adding translation \"" << key << "\" --> \"" << translation << "\"" << PLS_ENDL; + translation_map[key] = translation; + } +} + +#if LL_GTK +namespace LLWindowSDL { + bool ll_try_gtk_init(void) + { + static BOOL done_gtk_diag = FALSE; + static BOOL gtk_is_good = FALSE; + static BOOL done_setlocale = FALSE; + static BOOL tried_gtk_init = FALSE; + + if (!done_setlocale) + { + PLS_INFOS << "Starting GTK Initialization." << PLS_ENDL; + //maybe_lock_display(); + gtk_disable_setlocale(); + //maybe_unlock_display(); + done_setlocale = TRUE; + } + + if (!tried_gtk_init) + { + tried_gtk_init = TRUE; + if (!g_thread_supported ()) g_thread_init (NULL); + //maybe_lock_display(); + gtk_is_good = gtk_init_check(NULL, NULL); + //maybe_unlock_display(); + if (!gtk_is_good) + PLS_WARNS << "GTK Initialization failed." << PLS_ENDL; + } + if (gtk_is_good && !done_gtk_diag) + { + PLS_INFOS << "GTK Initialized." << PLS_ENDL; + PLS_INFOS << "- Compiled against GTK version " + << GTK_MAJOR_VERSION << "." + << GTK_MINOR_VERSION << "." + << GTK_MICRO_VERSION << PLS_ENDL; + PLS_INFOS << "- Running against GTK version " + << gtk_major_version << "." + << gtk_minor_version << "." + << gtk_micro_version << PLS_ENDL; + //maybe_lock_display(); + const gchar* gtk_warning = gtk_check_version( + GTK_MAJOR_VERSION, + GTK_MINOR_VERSION, + GTK_MICRO_VERSION); + //maybe_unlock_display(); + if (gtk_warning) + { + PLS_WARNS << "- GTK COMPATIBILITY WARNING: " << gtk_warning << PLS_ENDL; + gtk_is_good = FALSE; + } + else + { + PLS_INFOS << "- GTK version is good." << PLS_ENDL; + } + done_gtk_diag = TRUE; + } + return gtk_is_good; + } +} +#endif + +// +// Globals +// + +LLFilePicker LLFilePicker::sInstance; + +#if LL_WINDOWS +#define SOUND_FILTER L"Sounds (*.wav)\0*.wav\0" +#define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png\0" +#define ANIM_FILTER L"Animations (*.bvh)\0*.bvh\0" +#ifdef _CORY_TESTING +#define GEOMETRY_FILTER L"SL Geometry (*.slg)\0*.slg\0" +#endif +#define XML_FILTER L"XML files (*.xml)\0*.xml\0" +#define SLOBJECT_FILTER L"Objects (*.slobject)\0*.slobject\0" +#define RAW_FILTER L"RAW files (*.raw)\0*.raw\0" +#endif + +// +// Implementation +// +LLFilePickerBase::LLFilePickerBase() + : mCurrentFile(0), + mLocked(FALSE) + +{ + reset(); + +#if LL_WINDOWS + mOFN.lStructSize = sizeof(OPENFILENAMEW); + mOFN.hwndOwner = NULL; // Set later with setWindowID + mOFN.hInstance = NULL; + mOFN.lpstrCustomFilter = NULL; + mOFN.nMaxCustFilter = 0; + mOFN.lpstrFile = NULL; // set in open and close + mOFN.nMaxFile = LL_MAX_PATH; + mOFN.lpstrFileTitle = NULL; + mOFN.nMaxFileTitle = 0; + mOFN.lpstrInitialDir = NULL; + mOFN.lpstrTitle = NULL; + mOFN.Flags = 0; // set in open and close + mOFN.nFileOffset = 0; + mOFN.nFileExtension = 0; + mOFN.lpstrDefExt = NULL; + mOFN.lCustData = 0L; + mOFN.lpfnHook = NULL; + mOFN.lpTemplateName = NULL; +#endif + +#if LL_DARWIN + memset(&mNavOptions, 0, sizeof(mNavOptions)); + OSStatus error = NavGetDefaultDialogCreationOptions(&mNavOptions); + if (error == noErr) + { + mNavOptions.modality = kWindowModalityAppModal; + } +#endif +} + +const std::string LLFilePickerBase::getFirstFile() +{ + mCurrentFile = 0; + return getNextFile(); +} + +const std::string LLFilePickerBase::getNextFile() +{ + if (mCurrentFile >= getFileCount()) + { + mLocked = FALSE; + return std::string(); + } + else + { + return mFiles[mCurrentFile++]; + } +} + +const std::string LLFilePickerBase::getCurFile() +{ + if (mCurrentFile >= getFileCount()) + { + mLocked = FALSE; + return std::string(); + } + else + { + return mFiles[mCurrentFile]; + } +} + +void LLFilePickerBase::reset() +{ + mLocked = FALSE; + mFiles.clear(); + mCurrentFile = 0; +} + +#if LL_WINDOWS + +bool LLFilePickerBase::setupFilter(ELoadFilter filter) +{ + bool res = TRUE; + switch (filter) + { + case FFLOAD_ALL: + mOFN.lpstrFilter = L"All Files (*.*)\0*.*\0" \ + SOUND_FILTER \ + IMAGE_FILTER \ + ANIM_FILTER \ + L"\0"; + break; + case FFLOAD_WAV: + mOFN.lpstrFilter = SOUND_FILTER \ + L"\0"; + break; + case FFLOAD_IMAGE: + mOFN.lpstrFilter = IMAGE_FILTER \ + L"\0"; + break; + case FFLOAD_ANIM: + mOFN.lpstrFilter = ANIM_FILTER \ + L"\0"; + break; +#ifdef _CORY_TESTING + case FFLOAD_GEOMETRY: + mOFN.lpstrFilter = GEOMETRY_FILTER \ + L"\0"; + break; +#endif + case FFLOAD_XML: + mOFN.lpstrFilter = XML_FILTER \ + L"\0"; + break; + case FFLOAD_SLOBJECT: + mOFN.lpstrFilter = SLOBJECT_FILTER \ + L"\0"; + break; + case FFLOAD_RAW: + mOFN.lpstrFilter = RAW_FILTER \ + L"\0"; + break; + default: + res = FALSE; + break; + } + return res; +} + +// FIXME: Use folder +bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder) +{ + if( mLocked ) + { + return FALSE; + } + bool success = FALSE; + + // don't provide default file selection + mFilesW[0] = '\0'; + + mOFN.lpstrFile = mFilesW; + mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE; + mOFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR ; + mOFN.nFilterIndex = 1; + + setupFilter(filter); + + // Modal, so pause agent + send_agent_pause(); + + reset(); + + // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!! + success = GetOpenFileName(&mOFN); + if (success) + { + std::string filename = utf16str_to_utf8str(llutf16string(mFilesW)); + mFiles.push_back(filename); + } + send_agent_resume(); + + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); + return success; +} + +// FIXME: Use folder +bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string const& folder) +{ + if( mLocked ) + { + return FALSE; + } + bool success = FALSE; + + // don't provide default file selection + mFilesW[0] = '\0'; + + mOFN.lpstrFile = mFilesW; + mOFN.nFilterIndex = 1; + mOFN.nMaxFile = FILENAME_BUFFER_SIZE; + mOFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | + OFN_EXPLORER | OFN_ALLOWMULTISELECT; + + setupFilter(filter); + + reset(); + + // Modal, so pause agent + send_agent_pause(); + // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!! + success = GetOpenFileName(&mOFN); // pauses until ok or cancel. + if( success ) + { + // The getopenfilename api doesn't tell us if we got more than + // one file, so we have to test manually by checking string + // lengths. + if( wcslen(mOFN.lpstrFile) > mOFN.nFileOffset ) /*Flawfinder: ignore*/ + { + std::string filename = utf16str_to_utf8str(llutf16string(mFilesW)); + mFiles.push_back(filename); + } + else + { + mLocked = TRUE; + WCHAR* tptrw = mFilesW; + std::string dirname; + while(1) + { + if (*tptrw == 0 && *(tptrw+1) == 0) // double '\0' + break; + if (*tptrw == 0) + tptrw++; // shouldn't happen? + std::string filename = utf16str_to_utf8str(llutf16string(tptrw)); + if (dirname.empty()) + dirname = filename + "\\"; + else + mFiles.push_back(dirname + filename); + tptrw += filename.size(); + } + } + } + send_agent_resume(); + + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); + return success; +} + +// FIXME: Use folder +bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filename, std::string const& folder) +{ + if( mLocked ) + { + return FALSE; + } + bool success = FALSE; + + mOFN.lpstrFile = mFilesW; + if (!filename.empty()) + { + llutf16string tstring = utf8str_to_utf16str(filename); + wcsncpy(mFilesW, tstring.c_str(), FILENAME_BUFFER_SIZE); } /*Flawfinder: ignore*/ + else + { + mFilesW[0] = '\0'; + } + + switch( filter ) + { + case FFSAVE_ALL: + mOFN.lpstrDefExt = NULL; + mOFN.lpstrFilter = + L"All Files (*.*)\0*.*\0" \ + L"WAV Sounds (*.wav)\0*.wav\0" \ + L"Targa, Bitmap Images (*.tga; *.bmp)\0*.tga;*.bmp\0" \ + L"\0"; + break; + case FFSAVE_LSL: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.lsl", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"lsl"; + mOFN.lpstrFilter = + L"LSL Files (*.lsl)\0*.lsl\0" + L"Text files (*.txt)\0*.txt\0" + L"\0"; + break; + case FFSAVE_TEXT: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.txt", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"txt"; + mOFN.lpstrFilter = + L"Text files (*.txt)\0*.txt\0" + L"RTF Files (*.rtf)\0*.rtf\0" + L"\0"; + break; + case FFSAVE_WAV: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.wav", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"wav"; + mOFN.lpstrFilter = + L"WAV Sounds (*.wav)\0*.wav\0" \ + L"\0"; + break; + case FFSAVE_TGA: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.tga", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"tga"; + mOFN.lpstrFilter = + L"Targa Images (*.tga)\0*.tga\0" \ + L"\0"; + break; + case FFSAVE_BMP: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.bmp", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"bmp"; + mOFN.lpstrFilter = + L"Bitmap Images (*.bmp)\0*.bmp\0" \ + L"\0"; + break; + case FFSAVE_PNG: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.png", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"png"; + mOFN.lpstrFilter = + L"PNG Images (*.png)\0*.png\0" \ + L"\0"; + break; + case FFSAVE_JPEG: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.jpeg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"jpeg"; + mOFN.lpstrFilter = + L"JPEG Images (*.jpeg)\0*.jpeg\0" \ + L"\0"; + break; + case FFSAVE_AVI: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.avi", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"avi"; + mOFN.lpstrFilter = + L"AVI Movie File (*.avi)\0*.avi\0" \ + L"\0"; + break; + case FFSAVE_ANIM: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.xaf", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"xaf"; + mOFN.lpstrFilter = + L"XAF Anim File (*.xaf)\0*.xaf\0" \ + L"\0"; + break; +#ifdef _CORY_TESTING + case FFSAVE_GEOMETRY: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.slg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"slg"; + mOFN.lpstrFilter = + L"SLG SL Geometry File (*.slg)\0*.slg\0" \ + L"\0"; + break; +#endif + case FFSAVE_XML: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.xml", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + + mOFN.lpstrDefExt = L"xml"; + mOFN.lpstrFilter = + L"XML File (*.xml)\0*.xml\0" \ + L"\0"; + break; + case FFSAVE_COLLADA: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.collada", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"collada"; + mOFN.lpstrFilter = + L"COLLADA File (*.collada)\0*.collada\0" \ + L"\0"; + break; + case FFSAVE_RAW: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.raw", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"raw"; + mOFN.lpstrFilter = RAW_FILTER \ + L"\0"; + break; + case FFSAVE_J2C: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.j2c", FILENAME_BUFFER_SIZE); + } + mOFN.lpstrDefExt = L"j2c"; + mOFN.lpstrFilter = + L"Compressed Images (*.j2c)\0*.j2c\0" \ + L"\0"; + break; + default: + return FALSE; + } + + + mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE; + mOFN.Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST; + + reset(); + + // Modal, so pause agent + send_agent_pause(); + { + // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!! + success = GetSaveFileName(&mOFN); + if (success) + { + std::string filename = utf16str_to_utf8str(llutf16string(mFilesW)); + mFiles.push_back(filename); + } + gKeyboard->resetKeys(); + } + send_agent_resume(); + + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); + return success; +} + +#elif LL_DARWIN + +Boolean LLFilePickerBase::navOpenFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode) +{ + Boolean result = true; + ELoadFilter filter = *((ELoadFilter*) callBackUD); + OSStatus error = noErr; + + if (filterMode == kNavFilteringBrowserList && filter != FFLOAD_ALL && (theItem->descriptorType == typeFSRef || theItem->descriptorType == typeFSS)) + { + // navInfo is only valid for typeFSRef and typeFSS + NavFileOrFolderInfo *navInfo = (NavFileOrFolderInfo*) info; + if (!navInfo->isFolder) + { + AEDesc desc; + error = AECoerceDesc(theItem, typeFSRef, &desc); + if (error == noErr) + { + FSRef fileRef; + error = AEGetDescData(&desc, &fileRef, sizeof(fileRef)); + if (error == noErr) + { + LSItemInfoRecord fileInfo; + error = LSCopyItemInfoForRef(&fileRef, kLSRequestExtension | kLSRequestTypeCreator, &fileInfo); + if (error == noErr) + { + if (filter == FFLOAD_IMAGE) + { + if (fileInfo.filetype != 'JPEG' && fileInfo.filetype != 'JPG ' && + fileInfo.filetype != 'BMP ' && fileInfo.filetype != 'TGA ' && + fileInfo.filetype != 'TIFF' && fileInfo.filetype != 'PSD ' && + fileInfo.filetype != 'BMPf' && fileInfo.filetype != 'TPIC' && + fileInfo.filetype != 'PNG ' && + (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("jpeg"), kCFCompareCaseInsensitive) != kCFCompareEqualTo && + CFStringCompare(fileInfo.extension, CFSTR("jpg"), kCFCompareCaseInsensitive) != kCFCompareEqualTo && + CFStringCompare(fileInfo.extension, CFSTR("bmp"), kCFCompareCaseInsensitive) != kCFCompareEqualTo && + CFStringCompare(fileInfo.extension, CFSTR("tga"), kCFCompareCaseInsensitive) != kCFCompareEqualTo && + CFStringCompare(fileInfo.extension, CFSTR("psd"), kCFCompareCaseInsensitive) != kCFCompareEqualTo && + CFStringCompare(fileInfo.extension, CFSTR("tiff"), kCFCompareCaseInsensitive) != kCFCompareEqualTo && + CFStringCompare(fileInfo.extension, CFSTR("tif"), kCFCompareCaseInsensitive) != kCFCompareEqualTo && + CFStringCompare(fileInfo.extension, CFSTR("png"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) + ) + { + result = false; + } + } + else if (filter == FFLOAD_WAV) + { + if (fileInfo.filetype != 'WAVE' && fileInfo.filetype != 'WAV ' && + (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("wave"), kCFCompareCaseInsensitive) != kCFCompareEqualTo && + CFStringCompare(fileInfo.extension, CFSTR("wav"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) + ) + { + result = false; + } + } + else if (filter == FFLOAD_ANIM) + { + if (fileInfo.filetype != 'BVH ' && + (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("bvh"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) + ) + { + result = false; + } + } +#ifdef _CORY_TESTING + else if (filter == FFLOAD_GEOMETRY) + { + if (fileInfo.filetype != 'SLG ' && + (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("slg"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) + ) + { + result = false; + } + } +#endif + else if (filter == FFLOAD_SLOBJECT) + { + PLS_WARNS << "*** navOpenFilterProc: FFLOAD_SLOBJECT NOT IMPLEMENTED ***" << PLS_ENDL; + } + else if (filter == FFLOAD_RAW) + { + if (fileInfo.filetype != '\?\?\?\?' && + (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("raw"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) + ) + { + result = false; + } + } + + if (fileInfo.extension) + { + CFRelease(fileInfo.extension); + } + } + } + AEDisposeDesc(&desc); + } + } + } + return result; +} + +OSStatus LLFilePickerBase::doNavChooseDialog(ELoadFilter filter) +{ + OSStatus error = noErr; + NavDialogRef navRef = NULL; + NavReplyRecord navReply; + + memset(&navReply, 0, sizeof(navReply)); + + // NOTE: we are passing the address of a local variable here. + // This is fine, because the object this call creates will exist for less than the lifetime of this function. + // (It is destroyed by NavDialogDispose() below.) + error = NavCreateChooseFileDialog(&mNavOptions, NULL, NULL, NULL, navOpenFilterProc, (void*)(&filter), &navRef); + + //gViewerWindow->mWindow->beforeDialog(); + + if (error == noErr) + error = NavDialogRun(navRef); + + //gViewerWindow->mWindow->afterDialog(); + + if (error == noErr) + error = NavDialogGetReply(navRef, &navReply); + + if (navRef) + NavDialogDispose(navRef); + + if (error == noErr && navReply.validRecord) + { + SInt32 count = 0; + SInt32 index; + + // AE indexes are 1 based... + error = AECountItems(&navReply.selection, &count); + for (index = 1; index <= count; index++) + { + FSRef fsRef; + AEKeyword theAEKeyword; + DescType typeCode; + Size actualSize = 0; + char path[MAX_PATH]; /*Flawfinder: ignore*/ + + memset(&fsRef, 0, sizeof(fsRef)); + error = AEGetNthPtr(&navReply.selection, index, typeFSRef, &theAEKeyword, &typeCode, &fsRef, sizeof(fsRef), &actualSize); + + if (error == noErr) + error = FSRefMakePath(&fsRef, (UInt8*) path, sizeof(path)); + + if (error == noErr) + mFiles.push_back(std::string(path)); + } + } + + return error; +} + +OSStatus LLFilePickerBase::doNavSaveDialog(ESaveFilter filter, const std::string& filename) +{ + OSStatus error = noErr; + NavDialogRef navRef = NULL; + NavReplyRecord navReply; + + memset(&navReply, 0, sizeof(navReply)); + + // Setup the type, creator, and extension + OSType type, creator; + CFStringRef extension = NULL; + switch (filter) + { + case FFSAVE_WAV: + type = 'WAVE'; + creator = 'TVOD'; + extension = CFSTR(".wav"); + break; + + case FFSAVE_TGA: + type = 'TPIC'; + creator = 'prvw'; + extension = CFSTR(".tga"); + break; + + case FFSAVE_BMP: + type = 'BMPf'; + creator = 'prvw'; + extension = CFSTR(".bmp"); + break; + case FFSAVE_JPEG: + type = 'JPEG'; + creator = 'prvw'; + extension = CFSTR(".jpeg"); + break; + case FFSAVE_PNG: + type = 'PNG '; + creator = 'prvw'; + extension = CFSTR(".png"); + break; + case FFSAVE_AVI: + type = '\?\?\?\?'; + creator = '\?\?\?\?'; + extension = CFSTR(".mov"); + break; + + case FFSAVE_ANIM: + type = '\?\?\?\?'; + creator = '\?\?\?\?'; + extension = CFSTR(".xaf"); + break; + +#ifdef _CORY_TESTING + case FFSAVE_GEOMETRY: + type = '\?\?\?\?'; + creator = '\?\?\?\?'; + extension = CFSTR(".slg"); + break; +#endif + case FFSAVE_RAW: + type = '\?\?\?\?'; + creator = '\?\?\?\?'; + extension = CFSTR(".raw"); + break; + + case FFSAVE_J2C: + type = '\?\?\?\?'; + creator = 'prvw'; + extension = CFSTR(".j2c"); + break; + + case FFSAVE_ALL: + default: + type = '\?\?\?\?'; + creator = '\?\?\?\?'; + extension = CFSTR(""); + break; + } + + // Create the dialog + error = NavCreatePutFileDialog(&mNavOptions, type, creator, NULL, NULL, &navRef); + if (error == noErr) + { + CFStringRef nameString = NULL; + bool hasExtension = true; + + // Create a CFString of the initial file name + if (!filename.empty()) + nameString = CFStringCreateWithCString(NULL, filename.c_str(), kCFStringEncodingUTF8); + else + nameString = CFSTR("Untitled"); + + // Add the extension if one was not provided + if (nameString && !CFStringHasSuffix(nameString, extension)) + { + CFStringRef tempString = nameString; + hasExtension = false; + nameString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), tempString, extension); + CFRelease(tempString); + } + + // Set the name in the dialog + if (nameString) + { + error = NavDialogSetSaveFileName(navRef, nameString); + CFRelease(nameString); + } + else + { + error = paramErr; + } + } + + //gViewerWindow->mWindow->beforeDialog(); + + // Run the dialog + if (error == noErr) + error = NavDialogRun(navRef); + + //gViewerWindow->mWindow->afterDialog(); + + if (error == noErr) + error = NavDialogGetReply(navRef, &navReply); + + if (navRef) + NavDialogDispose(navRef); + + if (error == noErr && navReply.validRecord) + { + SInt32 count = 0; + + // AE indexes are 1 based... + error = AECountItems(&navReply.selection, &count); + if (count > 0) + { + // Get the FSRef to the containing folder + FSRef fsRef; + AEKeyword theAEKeyword; + DescType typeCode; + Size actualSize = 0; + + memset(&fsRef, 0, sizeof(fsRef)); + error = AEGetNthPtr(&navReply.selection, 1, typeFSRef, &theAEKeyword, &typeCode, &fsRef, sizeof(fsRef), &actualSize); + + if (error == noErr) + { + char path[PATH_MAX]; /*Flawfinder: ignore*/ + char newFileName[SINGLE_FILENAME_BUFFER_SIZE]; /*Flawfinder: ignore*/ + + error = FSRefMakePath(&fsRef, (UInt8*)path, PATH_MAX); + if (error == noErr) + { + if (CFStringGetCString(navReply.saveFileName, newFileName, sizeof(newFileName), kCFStringEncodingUTF8)) + { + mFiles.push_back(std::string(path) + "/" + std::string(newFileName)); + } + else + { + error = paramErr; + } + } + else + { + error = paramErr; + } + } + } + } + + return error; +} + +// FIXME: Use folder +bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder) +{ + if( mLocked ) + return FALSE; + + bool success = FALSE; + + OSStatus error = noErr; + + reset(); + + mNavOptions.optionFlags &= ~kNavAllowMultipleFiles; + // Modal, so pause agent + send_agent_pause(); + { + error = doNavChooseDialog(filter); + } + send_agent_resume(); + if (error == noErr) + { + if (getFileCount()) + success = true; + } + + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); + return success; +} + +// FIXME: Use folder +bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string const& folder) +{ + if( mLocked ) + return FALSE; + + bool success = FALSE; + + OSStatus error = noErr; + + reset(); + + mNavOptions.optionFlags |= kNavAllowMultipleFiles; + // Modal, so pause agent + send_agent_pause(); + { + error = doNavChooseDialog(filter); + } + send_agent_resume(); + if (error == noErr) + { + if (getFileCount()) + success = true; + if (getFileCount() > 1) + mLocked = TRUE; + } + + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); + return success; +} + +// FIXME: Use folder +bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filename, std::string const& folder) +{ + if( mLocked ) + return FALSE; + bool success = FALSE; + OSStatus error = noErr; + + reset(); + + mNavOptions.optionFlags &= ~kNavAllowMultipleFiles; + + // Modal, so pause agent + send_agent_pause(); + { + error = doNavSaveDialog(filter, filename); + } + send_agent_resume(); + if (error == noErr) + { + if (getFileCount()) + success = true; + } + + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); + return success; +} + +#elif LL_LINUX || LL_SOLARIS + +# if LL_GTK + +// static +void LLFilePickerBase::add_to_selectedfiles(gpointer data, gpointer user_data) +{ + // We need to run g_filename_to_utf8 in the user's locale + std::string saved_locale(setlocale(LC_ALL, NULL)); + setlocale(LC_ALL, ""); + + LLFilePickerBase* picker = (LLFilePickerBase*) user_data; + GError *error = NULL; +// gchar* filename_utf8 = g_filename_to_utf8((gchar*)data, +// -1, NULL, NULL, &error); + gchar* filename_utf8 = g_filename_display_name ((gchar*) data); + if (error) + { + // *FIXME. + // This condition should really be notified to the user, e.g. + // through a message box. Just logging it is inappropriate. + + // Ghhhh. g_filename_display_name is new to glib 2.6, and it + // is too new for SL! (Note that the latest glib as of this + // writing is 2.22. *sigh*) LL supplied *makeASCII family are + // also unsuitable since they allow control characters... + + // muhahaha ... Imprudence can ! + + + PLS_WARNS << "g_filename_display_name failed on" << filename_utf8 << ": "<< error->message << PLS_ENDL; + } + + if (filename_utf8) + { + picker->mFiles.push_back(std::string(filename_utf8)); + PLS_DEBUGS << "ADDED FILE " << filename_utf8 << PLS_ENDL; + g_free(filename_utf8); + } + + setlocale(LC_ALL, saved_locale.c_str()); +} + +// static +void LLFilePickerBase::chooser_responder(GtkWidget *widget, gint response, gpointer user_data) +{ + LLFilePicker* picker = (LLFilePicker*)user_data; + + PLS_DEBUGS << "GTK DIALOG RESPONSE " << response << PLS_ENDL; + + if (response == GTK_RESPONSE_ACCEPT) + { + GSList *file_list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget)); + g_slist_foreach(file_list, (GFunc)add_to_selectedfiles, user_data); + g_slist_foreach(file_list, (GFunc)g_free, NULL); + g_slist_free (file_list); + } + + gtk_widget_destroy(widget); + gtk_main_quit(); +} + + +GtkWindow* LLFilePickerBase::buildFilePicker(bool is_save, bool is_folder, std::string const& folder) +{ + if (LLWindowSDL::ll_try_gtk_init()) + { + GtkWidget *win = NULL; + GtkFileChooserAction pickertype = + is_save? + (is_folder? + GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER : + GTK_FILE_CHOOSER_ACTION_SAVE) : + (is_folder? + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER : + GTK_FILE_CHOOSER_ACTION_OPEN); + + win = gtk_file_chooser_dialog_new(NULL, NULL, + pickertype, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + is_folder ? + GTK_STOCK_APPLY : + (is_save ? + GTK_STOCK_SAVE : + GTK_STOCK_OPEN), + GTK_RESPONSE_ACCEPT, + (gchar *)NULL); + + if (!folder.empty()) + { + gtk_file_chooser_set_current_folder + (GTK_FILE_CHOOSER(win), + folder.c_str()); + } + +# if LL_X11 + // Make GTK tell the window manager to associate this + // dialog with our non-GTK raw X11 window, which should try + // to keep it on top etc. + if (mX11WindowID != None) + { + gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin + GdkWindow *gdkwin = gdk_window_foreign_new(mX11WindowID); + gdk_window_set_transient_for(GTK_WIDGET(win)->window, gdkwin); + } +# endif //LL_X11 + + g_signal_connect (GTK_FILE_CHOOSER(win), + "response", + G_CALLBACK(LLFilePickerBase::chooser_responder), + this); + + gtk_window_set_modal(GTK_WINDOW(win), TRUE); + + /* GTK 2.6: if (is_folder) + gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(win), + TRUE); */ + + return GTK_WINDOW(win); + } + else + { + return NULL; + } +} + +static void add_common_filters_to_gtkchooser(GtkFileFilter *gfilter, + GtkWindow *picker, + std::string filtername) +{ + gtk_file_filter_set_name(gfilter, filtername.c_str()); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), + gfilter); + GtkFileFilter *allfilter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(allfilter, "*"); + gtk_file_filter_set_name(allfilter, LLTrans::getString("all_files").c_str()); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), allfilter); + gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(picker), gfilter); +} + +static std::string add_simple_pattern_filter_to_gtkchooser(GtkWindow *picker, + std::string pattern, + std::string filtername) +{ + GtkFileFilter *gfilter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(gfilter, pattern.c_str()); + add_common_filters_to_gtkchooser(gfilter, picker, filtername); + return filtername; +} + +static std::string add_simple_mime_filter_to_gtkchooser(GtkWindow *picker, + std::string mime, + std::string filtername) +{ + GtkFileFilter *gfilter = gtk_file_filter_new(); + gtk_file_filter_add_mime_type(gfilter, mime.c_str()); + add_common_filters_to_gtkchooser(gfilter, picker, filtername); + return filtername; +} + +static std::string add_wav_filter_to_gtkchooser(GtkWindow *picker) +{ + GtkFileFilter *gfilter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(gfilter, "*.wav"); + gtk_file_filter_add_mime_type(gfilter,"audio/x-wav");//not working + + std::string filtername = LLTrans::getString("sound_files") + " (*.wav)"; + add_common_filters_to_gtkchooser(gfilter, picker, filtername); + return filtername; +} + +static std::string add_bvh_filter_to_gtkchooser(GtkWindow *picker) +{ + return add_simple_pattern_filter_to_gtkchooser(picker, "*.bvh", + LLTrans::getString("animation_files") + " (*.bvh)"); +} + +static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker) +{ + GtkFileFilter *gfilter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(gfilter, "*.tga"); + gtk_file_filter_add_mime_type(gfilter, "image/jpeg"); + gtk_file_filter_add_mime_type(gfilter, "image/png"); + gtk_file_filter_add_mime_type(gfilter, "image/bmp"); + std::string filtername = LLTrans::getString("image_files") + " (*.tga; *.bmp; *.jpg; *.png)"; + add_common_filters_to_gtkchooser(gfilter, picker, filtername); + return filtername; +} + + +bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filename, std::string const& folder) +{ + bool rtn = FALSE; + + //gViewerWindow->mWindow->beforeDialog(); + + reset(); + + GtkWindow* picker = buildFilePicker(true, false, folder); + + if (picker) + { + std::string suggest_name = "untitled"; + std::string suggest_ext = ""; + std::string caption = LLTrans::getString("save_file_verb") + " "; + switch (filter) + { + case FFSAVE_WAV: + caption += add_wav_filter_to_gtkchooser(picker); + suggest_ext = ".wav"; + break; + case FFSAVE_TGA: + caption += add_simple_pattern_filter_to_gtkchooser + (picker, "*.tga", LLTrans::getString("targa_image_files") + " (*.tga)"); + suggest_ext = ".tga"; + break; + case FFSAVE_BMP: + caption += add_simple_mime_filter_to_gtkchooser + (picker, "image/bmp", LLTrans::getString("bitmap_image_files") + " (*.bmp)"); + suggest_ext = ".bmp"; + break; + case FFSAVE_AVI: + caption += add_simple_mime_filter_to_gtkchooser + (picker, "video/x-msvideo", + LLTrans::getString("avi_movie_file") + " (*.avi)"); + suggest_ext = ".avi"; + break; + case FFSAVE_ANIM: + caption += add_simple_pattern_filter_to_gtkchooser + (picker, "*.xaf", LLTrans::getString("xaf_animation_file") + " (*.xaf)"); + suggest_ext = ".xaf"; + break; + case FFSAVE_XML: + caption += add_simple_pattern_filter_to_gtkchooser + (picker, "*.xml", LLTrans::getString("xml_file") + " (*.xml)"); + suggest_ext = ".xml"; + break; + case FFSAVE_RAW: + caption += add_simple_pattern_filter_to_gtkchooser + (picker, "*.raw", LLTrans::getString("raw_file") + " (*.raw)"); + suggest_ext = ".raw"; + break; + case FFSAVE_J2C: + caption += add_simple_mime_filter_to_gtkchooser + (picker, "images/jp2", + LLTrans::getString("compressed_image_files") + " (*.j2c)"); + suggest_ext = ".j2c"; + break; + default:; + break; + } + + gtk_window_set_title(GTK_WINDOW(picker), caption.c_str()); + + if (filename.empty()) + { + suggest_name += suggest_ext; + + gtk_file_chooser_set_current_name + (GTK_FILE_CHOOSER(picker), + suggest_name.c_str()); + } + else + { + gtk_file_chooser_set_current_name + (GTK_FILE_CHOOSER(picker), filename.c_str()); + } + + gtk_widget_show_all(GTK_WIDGET(picker)); + gtk_main(); + + rtn = (getFileCount() == 1); + } + + //gViewerWindow->mWindow->afterDialog(); + + return rtn; +} + +bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder) +{ + bool rtn = FALSE; + + //gViewerWindow->mWindow->beforeDialog(); + + reset(); + + GtkWindow* picker = buildFilePicker(false, false, folder); + + if (picker) + { + std::string caption = LLTrans::getString("load_file_verb") + " "; + std::string filtername = ""; + switch (filter) + { + case FFLOAD_WAV: + filtername = add_wav_filter_to_gtkchooser(picker); + break; + case FFLOAD_ANIM: + filtername = add_bvh_filter_to_gtkchooser(picker); + break; + case FFLOAD_IMAGE: + filtername = add_imageload_filter_to_gtkchooser(picker); + break; + default:; + break; + } + + caption += filtername; + + gtk_window_set_title(GTK_WINDOW(picker), caption.c_str()); + + gtk_widget_show_all(GTK_WIDGET(picker)); + gtk_main(); + + rtn = (getFileCount() == 1); + } + + //gViewerWindow->mWindow->afterDialog(); + + return rtn; +} + +bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string const& folder) +{ + bool rtn = FALSE; + + //gViewerWindow->mWindow->beforeDialog(); + + reset(); + + GtkWindow* picker = buildFilePicker(false, false, folder); + + if (picker) + { + gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(picker), + TRUE); + + gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("load_files").c_str()); + + gtk_widget_show_all(GTK_WIDGET(picker)); + gtk_main(); + rtn = !mFiles.empty(); + } + + //gViewerWindow->mWindow->afterDialog(); + + return rtn; +} + +# else // LL_GTK + +// Hacky stubs designed to facilitate fake getSaveFile and getLoadFile with +// static results, when we don't have a real filepicker. + +bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filename, std::string const& folder) +{ + reset(); + + PLS_INFOS << "getSaveFile suggested filename is [" << filename << "]" << PLS_ENDL; + if (!filename.empty()) + { + mFiles.push_back(gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + filename); + return TRUE; + } + return FALSE; +} + +// FIXME: Use folder +bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder) +{ + reset(); + + // HACK: Static filenames for 'open' until we implement filepicker + std::string filename = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + "upload"; + switch (filter) + { + case FFLOAD_WAV: filename += ".wav"; break; + case FFLOAD_IMAGE: filename += ".tga"; break; + case FFLOAD_ANIM: filename += ".bvh"; break; + default: break; + } + mFiles.push_back(filename); + PLS_INFOS << "getLoadFile: Will try to open file: " << hackyfilename << PLS_ENDL; + return TRUE; +} + +bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string const& folder) +{ + reset(); + return FALSE; +} + +#endif // LL_GTK + +#else // not implemented + +bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filename, std::string const& folder) +{ + reset(); + return FALSE; +} + +bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder) +{ + reset(); + return FALSE; +} + +bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string const& folder) +{ + reset(); + return FALSE; +} + +#endif diff --git a/indra/plugins/filepicker/llfilepicker.h b/indra/plugins/filepicker/llfilepicker.h new file mode 100644 index 000000000..d14612112 --- /dev/null +++ b/indra/plugins/filepicker/llfilepicker.h @@ -0,0 +1,231 @@ +/** + * @file llfilepicker.h + * @brief OS-specific file picker + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// OS specific file selection dialog. This is implemented as a +// singleton class, so call the instance() method to get the working +// instance. When you call getMultipleLoadFile(), it locks the picker +// until you iterate to the end of the list of selected files with +// getNextFile() or call reset(). + +#ifndef LL_LLFILEPICKER_H +#define LL_LLFILEPICKER_H + +#include "stdtypes.h" +#include +#include +#include + +#if LL_DARWIN +#include + +// AssertMacros.h does bad things. +#undef verify +#undef check +#undef require + +#include "llstring.h" + +#endif + +// Need commdlg.h for OPENFILENAMEA +#ifdef LL_WINDOWS +#include +#endif + +// mostly for Linux, possible on others +#if LL_GTK +# include "gtk/gtk.h" +#endif // LL_GTK + +// also mostly for Linux, for some X11-specific filepicker usability tweaks +#if LL_X11 +#include "SDL/SDL_syswm.h" +#endif + +// This class is used as base class of a singleton and is therefore not +// allowed to have any static members or static local variables! +class LLFilePickerBase +{ +public: + enum ELoadFilter + { + FFLOAD_ALL = 1, + FFLOAD_WAV = 2, + FFLOAD_IMAGE = 3, + FFLOAD_ANIM = 4, +#ifdef _CORY_TESTING + FFLOAD_GEOMETRY = 5, +#endif + FFLOAD_XML = 6, + FFLOAD_SLOBJECT = 7, + FFLOAD_RAW = 8, + FFLOAD_TEXT = 9, + }; + + enum ESaveFilter + { + FFSAVE_ALL = 1, + FFSAVE_WAV = 3, + FFSAVE_TGA = 4, + FFSAVE_BMP = 5, + FFSAVE_AVI = 6, + FFSAVE_ANIM = 7, +#ifdef _CORY_TESTING + FFSAVE_GEOMETRY = 8, +#endif + FFSAVE_XML = 9, + FFSAVE_COLLADA = 10, + FFSAVE_RAW = 11, + FFSAVE_J2C = 12, + FFSAVE_PNG = 13, + FFSAVE_JPEG = 14, + FFSAVE_HPA = 15, + FFSAVE_TEXT = 16, + FFSAVE_LSL = 17 + }; + + // open the dialog. This is a modal operation + bool getSaveFile(ESaveFilter filter, std::string const& filename, std::string const& folder); + bool getLoadFile(ELoadFilter filter, std::string const& folder); + bool getMultipleLoadFiles(ELoadFilter filter, std::string const& folder); + + // Get the filename(s) found. getFirstFile() sets the pointer to + // the start of the structure and allows the start of iteration. + const std::string getFirstFile(); + + // getNextFile() increments the internal representation and + // returns the next file specified by the user. Returns NULL when + // no more files are left. Further calls to getNextFile() are + // undefined. + const std::string getNextFile(); + + // This utility function extracts the current file name without + // doing any incrementing. + const std::string getCurFile(); + + // Returns the index of the current file. + S32 getCurFileNum() const { return mCurrentFile; } + + S32 getFileCount() const { return (S32)mFiles.size(); } + + // See llvfs/lldir.h : getBaseFileName and getDirName to extract base or directory names + + // clear any lists of buffers or whatever, and make sure the file + // picker isn't locked. + void reset(); + +private: + enum + { + SINGLE_FILENAME_BUFFER_SIZE = 1024, + //FILENAME_BUFFER_SIZE = 65536 + FILENAME_BUFFER_SIZE = 65000 + }; + +#if LL_WINDOWS + OPENFILENAMEW mOFN; // for open and save dialogs + WCHAR mFilesW[FILENAME_BUFFER_SIZE]; + +public: + void setWindowID(unsigned long window_id) { mOFN.hwndOwner = (HWND)window_id; } + +private: + bool setupFilter(ELoadFilter filter); +#endif // LL_WINDOWS + +#if LL_DARWIN + NavDialogCreationOptions mNavOptions; + std::vector mFileVector; + UInt32 mFileIndex; + + OSStatus doNavChooseDialog(ELoadFilter filter); + OSStatus doNavSaveDialog(ESaveFilter filter, const std::string& filename); + void getFilePath(SInt32 index); + void getFileName(SInt32 index); + static Boolean navOpenFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode); +#endif // LL_DARWIN + +#if LL_GTK + static void add_to_selectedfiles(gpointer data, gpointer user_data); + static void chooser_responder(GtkWidget *widget, gint response, gpointer user_data); + // we remember the last path that was accessed for a particular usage + std::map mContextToPathMap; + std::string mCurContextName; +#if LL_X11 + Window mX11WindowID; +#endif + +public: + std::map & get_ContextToPathMap(void) { return mContextToPathMap; } +#if LL_X11 + void setWindowID(unsigned long window_id) { mX11WindowID = (Window)window_id; } +#endif + +#endif // LL_GTK +#if !LL_WINDOWS && !(LL_GTK && LL_X11) + void setWindowID(unsigned long window_id) { PLS_WARNS << "Calling unimplemented LLFilePickerBase::setWindowID" << PLS_ENDL; } +#endif + +private: + std::vector mFiles; + S32 mCurrentFile; + bool mLocked; + bool mMultiFile; + +protected: +#if LL_GTK + GtkWindow* buildFilePicker(bool is_save, bool is_folder, std::string const& folder); +#endif + +protected: + LLFilePickerBase(); +}; + +// True singleton, private constructors (and no friends). +class LLFilePicker : public LLFilePickerBase +{ +public: + // calling this before main() is undefined + static LLFilePicker& instance( void ) { return sInstance; } + +private: + static LLFilePicker sInstance; + + LLFilePicker() { } +}; + +namespace translation +{ + void add(std::string const& key, std::string const& translation); +} + +#endif diff --git a/indra/media_plugins/gstreamer010/CMakeLists.txt b/indra/plugins/gstreamer010/CMakeLists.txt similarity index 82% rename from indra/media_plugins/gstreamer010/CMakeLists.txt rename to indra/plugins/gstreamer010/CMakeLists.txt index 5786bd1e2..f8a2a510e 100644 --- a/indra/media_plugins/gstreamer010/CMakeLists.txt +++ b/indra/plugins/gstreamer010/CMakeLists.txt @@ -30,23 +30,13 @@ include_directories( ### media_plugin_gstreamer010 -if(NOT WORD_SIZE EQUAL 32) - if(WINDOWS) - add_definitions(/FIXED:NO) - else(WINDOWS) # not windows therefore gcc LINUX and DARWIN - add_definitions(-fPIC) - endif(WINDOWS) -endif(NOT WORD_SIZE EQUAL 32) - set(media_plugin_gstreamer010_SOURCE_FILES media_plugin_gstreamer010.cpp - llmediaimplgstreamer_syms.cpp llmediaimplgstreamervidplug.cpp ) set(media_plugin_gstreamer010_HEADER_FILES llmediaimplgstreamervidplug.h - llmediaimplgstreamer_syms.h llmediaimplgstreamertriviallogging.h ) @@ -69,4 +59,3 @@ add_dependencies(media_plugin_gstreamer010 ${LLCOMMON_LIBRARIES} ) - diff --git a/indra/plugins/gstreamer010/llmediaimplgstreamer.h b/indra/plugins/gstreamer010/llmediaimplgstreamer.h new file mode 100755 index 000000000..bfc443b9e --- /dev/null +++ b/indra/plugins/gstreamer010/llmediaimplgstreamer.h @@ -0,0 +1,60 @@ +/** + * @file llmediaimplgstreamer.h + * @author Tofu Linden + * @brief implementation that supports media playback via GStreamer. + * + * @cond + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +// header guard +#ifndef llmediaimplgstreamer_h +#define llmediaimplgstreamer_h + +#if LL_GSTREAMER010_ENABLED + +extern "C" { +#include +#include + +#include "apr_pools.h" +#include "apr_dso.h" +} + + +extern "C" { +gboolean llmediaimplgstreamer_bus_callback (GstBus *bus, + GstMessage *message, + gpointer data); +} + +#endif // LL_GSTREAMER010_ENABLED + +#endif // llmediaimplgstreamer_h diff --git a/indra/plugins/gstreamer010/llmediaimplgstreamertriviallogging.h b/indra/plugins/gstreamer010/llmediaimplgstreamertriviallogging.h new file mode 100755 index 000000000..bb90aa12f --- /dev/null +++ b/indra/plugins/gstreamer010/llmediaimplgstreamertriviallogging.h @@ -0,0 +1,65 @@ +/** + * @file llmediaimplgstreamertriviallogging.h + * @brief minimal logging utilities. + * + * @cond + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +#ifndef __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__ +#define __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__ + +#include + +///////////////////////////////////////////////////////////////////////// +// Debug/Info/Warning macros. +#if LL_WINDOWS +#include +#define LL_GETPID GetCurrentProcessId +#else +#include +#include +#define LL_GETPID getpid +#endif +#define MSGMODULEFOO "(media plugin)" +#define STDERRMSG(...) do{\ + fprintf(stderr, " pid:%d: ", (int)LL_GETPID());\ + fprintf(stderr, MSGMODULEFOO " %s:%d: ", __FUNCTION__, __LINE__);\ + fprintf(stderr, __VA_ARGS__);\ + fputc('\n',stderr);\ + }while(0) +#define NULLMSG(...) do{}while(0) + +#define DEBUGMSG NULLMSG +#define INFOMSG STDERRMSG +#define WARNMSG STDERRMSG +///////////////////////////////////////////////////////////////////////// + +#endif /* __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__ */ diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/indra/plugins/gstreamer010/llmediaimplgstreamervidplug.cpp old mode 100644 new mode 100755 similarity index 70% rename from indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp rename to indra/plugins/gstreamer010/llmediaimplgstreamervidplug.cpp index cdb7f4fae..5c8a99f0c --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp +++ b/indra/plugins/gstreamer010/llmediaimplgstreamervidplug.cpp @@ -1,28 +1,35 @@ /** - * @file llmediaimplgstreamervidplug.h + * @file llmediaimplgstreamervidplug.cpp * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl * * @cond - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 * - * 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. + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception * - * 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. + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. * - * 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 + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ @@ -34,15 +41,29 @@ #include #include -#include "llmediaimplgstreamer_syms.h" #include "llmediaimplgstreamertriviallogging.h" +// #include "llthread.h" #include "llmediaimplgstreamervidplug.h" - GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug); #define GST_CAT_DEFAULT gst_slvideo_debug +/* Filter signals and args *//* +enum +{ + *//* FILL ME *//* + LAST_SIGNAL +}; + +enum +{ + ARG_0 +}; + +#define SLV_SIZECAPS ", width=(int){1,2,4,8,16,32,64,128,256,512,1024}, height=(int){1,2,4,8,16,32,64,128,256,512,1024} " +#define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS ";" GST_VIDEO_CAPS_BGRx SLV_SIZECAPS +*/ #define SLV_SIZECAPS ", width=(int)[1,2048], height=(int)[1,2048] " #define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS @@ -74,9 +95,9 @@ gst_slvideo_base_init (gpointer gclass) }; GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); - llgst_element_class_add_pad_template (element_class, - llgst_static_pad_template_get (&sink_factory)); - llgst_element_class_set_details (element_class, &element_details); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory)); + gst_element_class_set_details (element_class, &element_details); } @@ -87,7 +108,7 @@ gst_slvideo_finalize (GObject * object) slvideo = GST_SLVIDEO (object); if (slvideo->caps) { - llgst_caps_unref(slvideo->caps); + gst_caps_unref(slvideo->caps); } G_OBJECT_CLASS(parent_class)->finalize (object); @@ -98,7 +119,7 @@ static GstFlowReturn gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf) { GstSLVideo *slvideo; - llg_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); slvideo = GST_SLVIDEO(bsink); @@ -190,7 +211,7 @@ gst_slvideo_get_caps (GstBaseSink * bsink) GstSLVideo *slvideo; slvideo = GST_SLVIDEO(bsink); - return llgst_caps_ref (slvideo->caps); + return gst_caps_ref (slvideo->caps); } @@ -200,21 +221,32 @@ gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps) { GstSLVideo *filter; GstStructure *structure; +// GstCaps *intersection; GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps); filter = GST_SLVIDEO(bsink); - int width, height; +/* + intersection = gst_caps_intersect (filter->caps, caps); + if (gst_caps_is_empty (intersection)) + { + // no overlap between our caps and requested caps + return FALSE; + } + gst_caps_unref(intersection); +*/ + int width = 0; + int height = 0; gboolean ret; const GValue *fps; const GValue *par; - structure = llgst_caps_get_structure (caps, 0); - ret = llgst_structure_get_int (structure, "width", &width); - ret = ret && llgst_structure_get_int (structure, "height", &height); - fps = llgst_structure_get_value (structure, "framerate"); + structure = gst_caps_get_structure (caps, 0); + ret = gst_structure_get_int (structure, "width", &width); + ret = ret && gst_structure_get_int (structure, "height", &height); + fps = gst_structure_get_value (structure, "framerate"); ret = ret && (fps != NULL); - par = llgst_structure_get_value (structure, "pixel-aspect-ratio"); + par = gst_structure_get_value (structure, "pixel-aspect-ratio"); if (!ret) return FALSE; @@ -224,34 +256,35 @@ gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps) filter->width = width; filter->height = height; - - filter->fps_n = llgst_value_get_fraction_numerator(fps); - filter->fps_d = llgst_value_get_fraction_denominator(fps); + filter->fps_n = gst_value_get_fraction_numerator(fps); + filter->fps_d = gst_value_get_fraction_denominator(fps); if (par) { - filter->par_n = llgst_value_get_fraction_numerator(par); - filter->par_d = llgst_value_get_fraction_denominator(par); + filter->par_n = gst_value_get_fraction_numerator(par); + filter->par_d = gst_value_get_fraction_denominator(par); } else { filter->par_n = 1; filter->par_d = 1; } + GST_VIDEO_SINK_WIDTH(filter) = width; GST_VIDEO_SINK_HEIGHT(filter) = height; - + // crufty lump - we *always* accept *only* RGBX now. /* + filter->format = SLV_PF_UNKNOWN; - if (0 == strcmp(llgst_structure_get_name(structure), + if (0 == strcmp(gst_structure_get_name(structure), "video/x-raw-rgb")) { int red_mask; int green_mask; int blue_mask; - llgst_structure_get_int(structure, "red_mask", &red_mask); - llgst_structure_get_int(structure, "green_mask", &green_mask); - llgst_structure_get_int(structure, "blue_mask", &blue_mask); + gst_structure_get_int(structure, "red_mask", &red_mask); + gst_structure_get_int(structure, "green_mask", &green_mask); + gst_structure_get_int(structure, "blue_mask", &blue_mask); if ((unsigned int)red_mask == 0xFF000000 && (unsigned int)green_mask == 0x00FF0000 && (unsigned int)blue_mask == 0x0000FF00) @@ -265,12 +298,13 @@ gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps) filter->format = SLV_PF_BGRX; //fprintf(stderr, "\n\nPIXEL FORMAT BGR\n\n"); } - }*/ - + + }*/ + filter->format = SLV_PF_RGBX; GST_OBJECT_UNLOCK(filter); - + return TRUE; } @@ -317,15 +351,15 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, // we can ignore these and reverse-negotiate our preferred dimensions with // the peer if we like - we need to do this to obey dynamic resize requests // flowing in from the app. - structure = llgst_caps_get_structure (caps, 0); - if (!llgst_structure_get_int(structure, "width", &width) || - !llgst_structure_get_int(structure, "height", &height)) + structure = gst_caps_get_structure (caps, 0); + if (!gst_structure_get_int(structure, "width", &width) || + !gst_structure_get_int(structure, "height", &height)) { GST_WARNING_OBJECT (slvideo, "no width/height in caps %" GST_PTR_FORMAT, caps); return GST_FLOW_NOT_NEGOTIATED; } - GstBuffer *newbuf = llgst_buffer_new(); + GstBuffer *newbuf = gst_buffer_new(); bool made_bufferdata_ptr = false; #define MAXDEPTHHACK 4 @@ -345,19 +379,19 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, GstCaps *desired_caps; GstStructure *desired_struct; - desired_caps = llgst_caps_copy (caps); - desired_struct = llgst_caps_get_structure (desired_caps, 0); + desired_caps = gst_caps_copy (caps); + desired_struct = gst_caps_get_structure (desired_caps, 0); GValue value = {0}; g_value_init(&value, G_TYPE_INT); g_value_set_int(&value, slwantwidth); - llgst_structure_set_value (desired_struct, "width", &value); + gst_structure_set_value (desired_struct, "width", &value); g_value_unset(&value); g_value_init(&value, G_TYPE_INT); g_value_set_int(&value, slwantheight); - llgst_structure_set_value (desired_struct, "height", &value); + gst_structure_set_value (desired_struct, "height", &value); - if (llgst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (slvideo), + if (gst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (slvideo), desired_caps)) { // todo: re-use buffers from a pool? @@ -368,13 +402,13 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, GST_BUFFER_SIZE(newbuf) = slwantwidth * slwantheight * MAXDEPTHHACK; GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf)); GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf); - llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), desired_caps); + gst_buffer_set_caps (GST_BUFFER_CAST(newbuf), desired_caps); made_bufferdata_ptr = true; } else { // peer hates our cap suggestion INFOMSG("peer hates us :("); - llgst_caps_unref(desired_caps); + gst_caps_unref(desired_caps); } } } @@ -386,7 +420,7 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK; GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf)); GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf); - llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps); + gst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps); } *buf = GST_BUFFER_CAST(newbuf); @@ -428,6 +462,20 @@ gst_slvideo_class_init (GstSLVideoClass * klass) #undef LLGST_DEBUG_FUNCPTR } +/* +static void +gst_slvideo_update_caps (GstSLVideo * slvideo) +{ + GstCaps *caps; + + // GStreamer will automatically convert colourspace if necessary. + // GStreamer will automatically resize media to one of these enumerated + // powers-of-two that we ask for (yay GStreamer!) + caps = gst_caps_from_string (SLV_ALLCAPS); + + gst_caps_replace (&slvideo->caps, caps); +} +*/ /* initialize the new element * instantiate pads and add them to element @@ -450,24 +498,24 @@ gst_slvideo_init (GstSLVideo * filter, filter->retained_frame_width = filter->width; filter->retained_frame_height = filter->height; filter->retained_frame_format = SLV_PF_UNKNOWN; - GstCaps *caps = llgst_caps_from_string (SLV_ALLCAPS); - llgst_caps_replace (&filter->caps, caps); + GstCaps *caps = gst_caps_from_string (SLV_ALLCAPS); + gst_caps_replace (&filter->caps, caps); filter->resize_forced_always = false; filter->resize_try_width = -1; filter->resize_try_height = -1; GST_OBJECT_UNLOCK(filter); + + //gst_slvideo_update_caps(filter); } static void gst_slvideo_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - llg_return_if_fail (GST_IS_SLVIDEO (object)); + g_return_if_fail (GST_IS_SLVIDEO (object)); - switch (prop_id) { - default: + if (prop_id) { G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; } } @@ -475,12 +523,10 @@ static void gst_slvideo_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - llg_return_if_fail (GST_IS_SLVIDEO (object)); + g_return_if_fail (GST_IS_SLVIDEO (object)); - switch (prop_id) { - default: + if (prop_id) { G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; } } @@ -498,7 +544,7 @@ plugin_init (GstPlugin * plugin) GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin", 0, (gchar*)"Second Life Video Sink"); - return llgst_element_register (plugin, "private-slvideo", + return gst_element_register (plugin, "private-slvideo", GST_RANK_NONE, GST_TYPE_SLVIDEO); } @@ -508,20 +554,19 @@ plugin_init (GstPlugin * plugin) some g++ versions buggily avoid __attribute__((constructor)) functions - so we provide an explicit plugin init function. */ -#define PACKAGE (gchar*)"packagehack" -// this macro quietly refers to PACKAGE internally -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - (gchar*)"private-slvideoplugin", - (gchar*)"SL Video sink plugin", - plugin_init, (gchar*)"1.0", (gchar*)"LGPL", - (gchar*)"Second Life", - (gchar*)"http://www.secondlife.com/"); -#undef PACKAGE + void gst_slvideo_init_class (void) { - ll_gst_plugin_register_static (&gst_plugin_desc); - DEBUGMSG("CLASS INIT"); + gst_plugin_register_static( GST_VERSION_MAJOR, + GST_VERSION_MINOR, + (const gchar *)"private-slvideoplugin", + (gchar *)"SL Video sink plugin", + plugin_init, + (const gchar *)"0.1", + GST_LICENSE_UNKNOWN, + (const gchar *)"Second Life", + (const gchar *)"Second Life", + (const gchar *)"http://www.secondlife.com/" ); } #endif // LL_GSTREAMER010_ENABLED diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h b/indra/plugins/gstreamer010/llmediaimplgstreamervidplug.h old mode 100644 new mode 100755 similarity index 65% rename from indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h rename to indra/plugins/gstreamer010/llmediaimplgstreamervidplug.h index 29d65fa4e..5e8c72c98 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h +++ b/indra/plugins/gstreamer010/llmediaimplgstreamervidplug.h @@ -3,26 +3,33 @@ * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl * * @cond - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 * - * 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. + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception * - * 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. + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. * - * 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 + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ @@ -35,6 +42,7 @@ extern "C" { #include #include #include +// #include } G_BEGIN_DECLS diff --git a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/indra/plugins/gstreamer010/media_plugin_gstreamer010.cpp old mode 100644 new mode 100755 similarity index 70% rename from indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp rename to indra/plugins/gstreamer010/media_plugin_gstreamer010.cpp index 352b63583..8d0dc31e2 --- a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp +++ b/indra/plugins/gstreamer010/media_plugin_gstreamer010.cpp @@ -3,31 +3,49 @@ * @brief GStreamer-0.10 plugin for LLMedia API plugin system * * @cond - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 * - * 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. + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception * - * 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. + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. * - * 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 + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ #include "linden_common.h" +// Needed for _getcwd() RC +#ifdef LL_WINDOWS +#include +#include +#include +#endif + +#ifdef LL_DARWIN +#include +#endif + #include "llgl.h" #include "llplugininstance.h" @@ -39,6 +57,7 @@ extern "C" { #include +#include } #include "llmediaimplgstreamer.h" @@ -46,14 +65,12 @@ extern "C" { #include "llmediaimplgstreamervidplug.h" -#include "llmediaimplgstreamer_syms.h" - ////////////////////////////////////////////////////////////////////////////// // class MediaPluginGStreamer010 : public MediaPluginBase { public: - MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance); ~MediaPluginGStreamer010(); /* virtual */ void receiveMessage(const char *message_string); @@ -61,6 +78,8 @@ public: static bool startup(); static bool closedown(); + static void set_gst_plugin_path(); + gboolean processGSTEvents(GstBus *bus, GstMessage *message); @@ -76,7 +95,7 @@ private: bool play(double rate); bool getTimePos(double &sec_out); - static const double MIN_LOOP_SEC = 1.0F; + #define MIN_LOOP_SEC 1.0F bool mIsLooping; @@ -132,11 +151,12 @@ private: bool mSeekWanted; double mSeekDestination; + + std::string mLastTitle; // Very GStreamer-specific GMainLoop *mPump; // event pump for this media GstElement *mPlaybin; - GstElement *mVisualizer; GstSLVideo *mVideoSink; }; @@ -144,9 +164,9 @@ private: bool MediaPluginGStreamer010::mDoneInit = false; MediaPluginGStreamer010::MediaPluginGStreamer010( - LLPluginInstance::sendMessageFunction host_send_func, - void *host_user_data ) : - MediaPluginBase(host_send_func, host_user_data), + LLPluginInstance::sendMessageFunction send_message_function, + LLPluginInstance* plugin_instance) : + MediaPluginBase(send_message_function, plugin_instance), mBusWatchID ( 0 ), mCurrentRowbytes ( 4 ), mTextureFormatPrimary ( GL_RGBA ), @@ -155,12 +175,11 @@ MediaPluginGStreamer010::MediaPluginGStreamer010( mSeekDestination(0.0), mPump ( NULL ), mPlaybin ( NULL ), - mVisualizer ( NULL ), mVideoSink ( NULL ), mCommand ( COMMAND_NONE ) { std::ostringstream str; - INFOMSG("MediaPluginGStreamer010 constructor - my PID=%u", U32(getpid())); + INFOMSG("MediaPluginGStreamer010 constructor - my PID=%u", U32(LL_GETPID())); } /////////////////////////////////////////////////////////////////////////////// @@ -191,149 +210,179 @@ MediaPluginGStreamer010::processGSTEvents(GstBus *bus, GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING) { DEBUGMSG("Got GST message type: %s", - LLGST_MESSAGE_TYPE_NAME (message)); + GST_MESSAGE_TYPE_NAME (message)); } else { // TODO: grok 'duration' message type DEBUGMSG("Got GST message type: %s", - LLGST_MESSAGE_TYPE_NAME (message)); + GST_MESSAGE_TYPE_NAME (message)); } - switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_BUFFERING: { - // NEEDS GST 0.10.11+ - if (llgst_message_parse_buffering) + switch (GST_MESSAGE_TYPE (message)) + { + case GST_MESSAGE_BUFFERING: { + // NEEDS GST 0.10.11+ and America discovered by C.Columbus gint percent = 0; - llgst_message_parse_buffering(message, &percent); + gst_message_parse_buffering(message, &percent); DEBUGMSG("GST buffering: %d%%", percent); - } - break; - } - case GST_MESSAGE_STATE_CHANGED: { - GstState old_state; - GstState new_state; - GstState pending_state; - llgst_message_parse_state_changed(message, - &old_state, - &new_state, - &pending_state); -#ifdef LL_GST_REPORT_STATE_CHANGES - // not generally very useful, and rather spammy. - DEBUGMSG("state change (old,,pending): %s,<%s>,%s", - get_gst_state_name(old_state), - get_gst_state_name(new_state), - get_gst_state_name(pending_state)); -#endif // LL_GST_REPORT_STATE_CHANGES - switch (new_state) { - case GST_STATE_VOID_PENDING: - break; - case GST_STATE_NULL: - break; - case GST_STATE_READY: - setStatus(STATUS_LOADED); - break; - case GST_STATE_PAUSED: - setStatus(STATUS_PAUSED); - break; - case GST_STATE_PLAYING: - setStatus(STATUS_PLAYING); break; } - break; - } - case GST_MESSAGE_ERROR: { - GError *err = NULL; - gchar *debug = NULL; + case GST_MESSAGE_STATE_CHANGED: { + GstState old_state; + GstState new_state; + GstState pending_state; + gst_message_parse_state_changed(message, + &old_state, + &new_state, + &pending_state); + #ifdef LL_GST_REPORT_STATE_CHANGES + // not generally very useful, and rather spammy. + DEBUGMSG("state change (old,,pending): %s,<%s>,%s", + get_gst_state_name(old_state), + get_gst_state_name(new_state), + get_gst_state_name(pending_state)); + #endif // LL_GST_REPORT_STATE_CHANGES - llgst_message_parse_error (message, &err, &debug); - WARNMSG("GST error: %s", err?err->message:"(unknown)"); - if (err) - g_error_free (err); - g_free (debug); - - mCommand = COMMAND_STOP; - - setStatus(STATUS_ERROR); - - break; - } - case GST_MESSAGE_INFO: { - if (llgst_message_parse_info) + switch (new_state) + { + case GST_STATE_VOID_PENDING: + break; + case GST_STATE_NULL: + break; + case GST_STATE_READY: + setStatus(STATUS_LOADED); + break; + case GST_STATE_PAUSED: + setStatus(STATUS_PAUSED); + break; + case GST_STATE_PLAYING: + setStatus(STATUS_PLAYING); + break; + } + break; + } + case GST_MESSAGE_ERROR: + { + GError *err = NULL; + gchar *debug = NULL; + + gst_message_parse_error (message, &err, &debug); + WARNMSG("GST error: %s", err?err->message:"(unknown)"); + if (err) + g_error_free (err); + g_free (debug); + + mCommand = COMMAND_STOP; + + setStatus(STATUS_ERROR); + + break; + } + case GST_MESSAGE_INFO: { GError *err = NULL; gchar *debug = NULL; - llgst_message_parse_info (message, &err, &debug); + gst_message_parse_info (message, &err, &debug); INFOMSG("GST info: %s", err?err->message:"(unknown)"); if (err) g_error_free (err); g_free (debug); + + break; } - break; - } - case GST_MESSAGE_WARNING: { - GError *err = NULL; - gchar *debug = NULL; - - llgst_message_parse_warning (message, &err, &debug); - WARNMSG("GST warning: %s", err?err->message:"(unknown)"); - if (err) - g_error_free (err); - g_free (debug); - - break; - } - case GST_MESSAGE_EOS: - /* end-of-stream */ - DEBUGMSG("GST end-of-stream."); - if (mIsLooping) + case GST_MESSAGE_WARNING: { - DEBUGMSG("looping media..."); - double eos_pos_sec = 0.0F; - bool got_eos_position = getTimePos(eos_pos_sec); + GError *err = NULL; + gchar *debug = NULL; + + gst_message_parse_warning (message, &err, &debug); + WARNMSG("GST warning: %s", err?err->message:"(unknown)"); + if (err) + g_error_free (err); + g_free (debug); + + break; + } + case GST_MESSAGE_TAG: + { + GstTagList *new_tags; - if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC) + gst_message_parse_tag( message, &new_tags ); + + gchar *title = NULL; + + if ( gst_tag_list_get_string(new_tags, GST_TAG_TITLE, &title) ) { - // if we know that the movie is really short, don't - // loop it else it can easily become a time-hog - // because of GStreamer spin-up overhead - DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec); - // inject a COMMAND_PAUSE - mCommand = COMMAND_PAUSE; - } - else - { -#undef LLGST_LOOP_BY_SEEKING -// loop with a stop-start instead of a seek, because it actually seems rather -// faster than seeking on remote streams. -#ifdef LLGST_LOOP_BY_SEEKING - // first, try looping by an explicit rewind - bool seeksuccess = seek(0.0); - if (seeksuccess) + //WARMING("Title: %s", title); + std::string newtitle(title); + gst_tag_list_free(new_tags); + + if ( newtitle != mLastTitle && !newtitle.empty() ) { - play(1.0); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", newtitle ); + sendMessage( message ); + mLastTitle = newtitle; + } + g_free(title); + } + + break; + } + case GST_MESSAGE_EOS: + { + /* end-of-stream */ + DEBUGMSG("GST end-of-stream."); + if (mIsLooping) + { + DEBUGMSG("looping media..."); + double eos_pos_sec = 0.0F; + bool got_eos_position = getTimePos(eos_pos_sec); + + if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC) + { + // if we know that the movie is really short, don't + // loop it else it can easily become a time-hog + // because of GStreamer spin-up overhead + DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec); + // inject a COMMAND_PAUSE + mCommand = COMMAND_PAUSE; } else -#endif // LLGST_LOOP_BY_SEEKING - { // use clumsy stop-start to loop - DEBUGMSG("didn't loop by rewinding - stopping and starting instead..."); - stop(); - play(1.0); + { + #undef LLGST_LOOP_BY_SEEKING + // loop with a stop-start instead of a seek, because it actually seems rather + // faster than seeking on remote streams. + #ifdef LLGST_LOOP_BY_SEEKING + // first, try looping by an explicit rewind + bool seeksuccess = seek(0.0); + if (seeksuccess) + { + play(1.0); + } + else + #endif // LLGST_LOOP_BY_SEEKING + { // use clumsy stop-start to loop + DEBUGMSG("didn't loop by rewinding - stopping and starting instead..."); + stop(); + play(1.0); + } } } - } - else // not a looping media - { - // inject a COMMAND_STOP - mCommand = COMMAND_STOP; - } - break; - default: - /* unhandled message */ - break; + else // not a looping media + { + // inject a COMMAND_STOP + mCommand = COMMAND_STOP; + } + } break; + + default: + /* unhandled message */ + break; } /* we want to be notified again the next time there is a message @@ -539,12 +588,8 @@ MediaPluginGStreamer010::pause() { DEBUGMSG("pausing media..."); // todo: error-check this? - if (mDoneInit && mPlaybin) - { - llgst_element_set_state(mPlaybin, GST_STATE_PAUSED); - return true; - } - return false; + gst_element_set_state(mPlaybin, GST_STATE_PAUSED); + return true; } bool @@ -552,12 +597,8 @@ MediaPluginGStreamer010::stop() { DEBUGMSG("stopping media..."); // todo: error-check this? - if (mDoneInit && mPlaybin) - { - llgst_element_set_state(mPlaybin, GST_STATE_READY); - return true; - } - return false; + gst_element_set_state(mPlaybin, GST_STATE_READY); + return true; } bool @@ -567,12 +608,8 @@ MediaPluginGStreamer010::play(double rate) DEBUGMSG("playing media... rate=%f", rate); // todo: error-check this? - if (mDoneInit && mPlaybin) - { - llgst_element_set_state(mPlaybin, GST_STATE_PLAYING); - return true; - } - return false; + gst_element_set_state(mPlaybin, GST_STATE_PLAYING); + return true; } bool @@ -600,7 +637,7 @@ MediaPluginGStreamer010::seek(double time_sec) bool success = false; if (mDoneInit && mPlaybin) { - success = llgst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME, + success = gst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME, GstSeekFlags(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT), GST_SEEK_TYPE_SET, gint64(time_sec*GST_SECOND), @@ -615,15 +652,13 @@ bool MediaPluginGStreamer010::getTimePos(double &sec_out) { bool got_position = false; - if (mDoneInit && mPlaybin) + if (mPlaybin) { gint64 pos; GstFormat timefmt = GST_FORMAT_TIME; - got_position = - llgst_element_query_position && - llgst_element_query_position(mPlaybin, - &timefmt, - &pos); + got_position = gst_element_query_position(mPlaybin, + &timefmt, + &pos); got_position = got_position && (timefmt == GST_FORMAT_TIME); // GStreamer may have other ideas, but we consider the current position @@ -665,7 +700,7 @@ MediaPluginGStreamer010::load() DEBUGMSG("setting up media..."); mIsLooping = false; - mVolume = 0.1234567; // minor hack to force an initial volume update + mVolume = (float) 0.1234567; // minor hack to force an initial volume update // Create a pumpable main-loop for this media mPump = g_main_loop_new (NULL, FALSE); @@ -676,7 +711,7 @@ MediaPluginGStreamer010::load() } // instantiate a playbin element to do the hard work - mPlaybin = llgst_element_factory_make ("playbin", "play"); + mPlaybin = gst_element_factory_make ("playbin", "play"); if (!mPlaybin) { setStatus(STATUS_ERROR); @@ -684,50 +719,21 @@ MediaPluginGStreamer010::load() } // get playbin's bus - GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin)); + GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mPlaybin)); if (!bus) { setStatus(STATUS_ERROR); return false; // error } - mBusWatchID = llgst_bus_add_watch (bus, + mBusWatchID = gst_bus_add_watch (bus, llmediaimplgstreamer_bus_callback, this); - llgst_object_unref (bus); - -#if 0 // not quite stable/correct yet - // get a visualizer element (bonus feature!) - char* vis_name = getenv("LL_GST_VIS_NAME"); - if (!vis_name || - (vis_name && std::string(vis_name)!="none")) - { - if (vis_name) - { - mVisualizer = llgst_element_factory_make (vis_name, "vis"); - } - if (!mVisualizer) - { - mVisualizer = llgst_element_factory_make ("libvisual_jess", "vis"); - if (!mVisualizer) - { - mVisualizer = llgst_element_factory_make ("goom", "vis"); - if (!mVisualizer) - { - mVisualizer = llgst_element_factory_make ("libvisual_lv_scope", "vis"); - if (!mVisualizer) - { - // That's okay, we don't NEED this. - } - } - } - } - } -#endif + gst_object_unref (bus); if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) { // instantiate a custom video sink mVideoSink = - GST_SLVIDEO(llgst_element_factory_make ("private-slvideo", "slvideo")); + GST_SLVIDEO(gst_element_factory_make ("private-slvideo", "slvideo")); if (!mVideoSink) { WARNMSG("Could not instantiate private-slvideo element."); @@ -740,11 +746,6 @@ MediaPluginGStreamer010::load() g_object_set(mPlaybin, "video-sink", mVideoSink, NULL); } - if (mVisualizer) - { - g_object_set(mPlaybin, "vis-plugin", mVisualizer, NULL); - } - return true; } @@ -762,17 +763,11 @@ MediaPluginGStreamer010::unload () if (mPlaybin) { - llgst_element_set_state (mPlaybin, GST_STATE_NULL); - llgst_object_unref (GST_OBJECT (mPlaybin)); + gst_element_set_state (mPlaybin, GST_STATE_NULL); + gst_object_unref (GST_OBJECT (mPlaybin)); mPlaybin = NULL; } - if (mVisualizer) - { - llgst_object_unref (GST_OBJECT (mVisualizer)); - mVisualizer = NULL; - } - if (mPump) { g_main_loop_quit(mPump); @@ -802,7 +797,10 @@ MediaPluginGStreamer010::startup() // Init the glib type system - we need it. g_type_init(); + set_gst_plugin_path(); + +/* // Get symbols! #if LL_DARWIN if (! grab_gst_syms("libgstreamer-0.10.dylib", @@ -818,24 +816,24 @@ MediaPluginGStreamer010::startup() WARNMSG("Couldn't find suitable GStreamer 0.10 support on this system - video playback disabled."); return false; } - - if (llgst_segtrap_set_enabled) - { - llgst_segtrap_set_enabled(FALSE); - } - else - { - WARNMSG("gst_segtrap_set_enabled() is not available; plugin crashes won't be caught."); - } - +*/ +// if (gst_segtrap_set_enabled) +// { + gst_segtrap_set_enabled(FALSE); +// } +// else +// { +// WARNMSG("gst_segtrap_set_enabled() is not available; plugin crashes won't be caught."); +// } +/* #if LL_LINUX // Gstreamer tries a fork during init, waitpid-ing on it, // which conflicts with any installed SIGCHLD handler... struct sigaction tmpact, oldact; - if (llgst_registry_fork_set_enabled) { + if (gst_registry_fork_set_enabled) { // if we can disable SIGCHLD-using forking behaviour, // do it. - llgst_registry_fork_set_enabled(false); + gst_registry_fork_set_enabled(false); } else { // else temporarily install default SIGCHLD handler @@ -846,24 +844,24 @@ MediaPluginGStreamer010::startup() sigaction(SIGCHLD, &tmpact, &oldact); } #endif // LL_LINUX - +*/ // Protect against GStreamer resetting the locale, yuck. static std::string saved_locale; saved_locale = setlocale(LC_ALL, NULL); // finally, try to initialize GStreamer! GError *err = NULL; - gboolean init_gst_success = llgst_init_check(NULL, NULL, &err); + gboolean init_gst_success = gst_init_check(NULL, NULL, &err); // restore old locale setlocale(LC_ALL, saved_locale.c_str() ); - +/* #if LL_LINUX // restore old SIGCHLD handler - if (!llgst_registry_fork_set_enabled) + if (!gst_registry_fork_set_enabled) sigaction(SIGCHLD, &oldact, NULL); #endif // LL_LINUX - +*/ if (!init_gst_success) // fail { if (err) @@ -877,16 +875,139 @@ MediaPluginGStreamer010::startup() } return false; } - + + // Set up logging facilities + gst_debug_remove_log_function( gst_debug_log_default ); +// gst_debug_add_log_function( gstreamer_log, NULL ); + // Init our custom plugins - only really need do this once. gst_slvideo_init_class(); - +/* + // List the plugins GStreamer can find + LL_DEBUGS("MediaImpl") << "Found GStreamer plugins:" << LL_ENDL; + GList *list; + GstRegistry *registry = gst_registry_get_default(); + std::string loaded = ""; + for (list = gst_registry_get_plugin_list(registry); + list != NULL; + list = g_list_next(list)) + { + GstPlugin *list_plugin = (GstPlugin *)list->data; + (bool)gst_plugin_is_loaded(list_plugin) ? loaded = "Yes" : loaded = "No"; + LL_DEBUGS("MediaImpl") << gst_plugin_get_name(list_plugin) << ", loaded? " << loaded << LL_ENDL; + } + gst_plugin_list_free(list); +*/ mDoneInit = true; } return true; } +void MediaPluginGStreamer010::set_gst_plugin_path() +{ + // Linux sets GST_PLUGIN_PATH in wrapper.sh, not here. +#if LL_WINDOWS || LL_DARWIN + + std::string imp_dir = ""; + + // Get the current working directory: +#if LL_WINDOWS + char* raw_dir; + raw_dir = _getcwd(NULL,0); + if( raw_dir != NULL ) + { + imp_dir = std::string( raw_dir ); + } +#elif LL_DARWIN + CFBundleRef main_bundle = CFBundleGetMainBundle(); + if( main_bundle != NULL ) + { + CFURLRef bundle_url = CFBundleCopyBundleURL( main_bundle ); + if( bundle_url != NULL ) + { + #ifndef MAXPATHLEN + #define MAXPATHLEN 1024 + #endif + char raw_dir[MAXPATHLEN]; + if( CFURLGetFileSystemRepresentation( bundle_url, true, (UInt8 *)raw_dir, MAXPATHLEN) ) + { + imp_dir = std::string( raw_dir ) + "/Contents/MacOS/"; + } + CFRelease(bundle_url); + } + } +#endif + + if( imp_dir == "" ) + { + WARNMSG("Could not get application directory, not setting GST_PLUGIN_PATH."); + return; + } + + DEBUGMSG("Imprudence is installed at %s", imp_dir); + + // ":" on Mac and 'Nix, ";" on Windows + std::string separator = G_SEARCHPATH_SEPARATOR_S; + + // Grab the current path, if it's set. + std::string old_plugin_path = ""; + char *old_path = getenv("GST_PLUGIN_PATH"); + if(old_path == NULL) + { + DEBUGMSG("Did not find user-set GST_PLUGIN_PATH."); + } + else + { + old_plugin_path = separator + std::string( old_path ); + } + + + // Search both Imprudence and Imprudence\lib\gstreamer-plugins. + // But we also want to search the path the user has set, if any. + std::string plugin_path = + "GST_PLUGIN_PATH=" + +#if LL_WINDOWS + imp_dir + "\\lib\\gstreamer-plugins" + +#elif LL_DARWIN + imp_dir + separator + + imp_dir + "/../Resources/lib/gstreamer-plugins" + +#endif + old_plugin_path; + + int put_result; + + // Place GST_PLUGIN_PATH in the environment settings +#if LL_WINDOWS + put_result = _putenv( (char*)plugin_path.c_str() ); +#elif LL_DARWIN + put_result = putenv( (char*)plugin_path.c_str() ); +#endif + + if( put_result == -1 ) + { + WARNMSG("Setting GST_PLUGIN_PATH failed!"); + } + else + { + DEBUGMSG("GST_PLUGIN_PATH set to %s", getenv("GST_PLUGIN_PATH")); + } + + // Don't load system plugins. We only want to use ours, to avoid conflicts. +#if LL_WINDOWS + put_result = _putenv( "GST_PLUGIN_SYSTEM_PATH=\"\"" ); +#elif LL_DARWIN + put_result = putenv( "GST_PLUGIN_SYSTEM_PATH=\"\"" ); +#endif + + if( put_result == -1 ) + { + WARNMSG("Setting GST_PLUGIN_SYSTEM_PATH=\"\" failed!"); + } + +#endif // LL_WINDOWS || LL_DARWIN +} + void MediaPluginGStreamer010::sizeChanged() @@ -928,7 +1049,7 @@ MediaPluginGStreamer010::closedown() if (!mDoneInit) return false; // error - ungrab_gst_syms(); +// ungrab_gst_syms(); mDoneInit = false; @@ -949,11 +1070,10 @@ std::string MediaPluginGStreamer010::getVersion() { std::string plugin_version = "GStreamer010 media plugin, GStreamer version "; - if (mDoneInit && - llgst_version) + if (mDoneInit) // && gst_version) { guint major, minor, micro, nano; - llgst_version(&major, &minor, µ, &nano); + gst_version(&major, &minor, µ, &nano); plugin_version += llformat("%u.%u.%u.%u (runtime), %u.%u.%u.%u (headers)", (unsigned int)major, (unsigned int)minor, (unsigned int)micro, (unsigned int)nano, (unsigned int)GST_VERSION_MAJOR, (unsigned int)GST_VERSION_MINOR, (unsigned int)GST_VERSION_MICRO, (unsigned int)GST_VERSION_NANO); } else @@ -1211,14 +1331,11 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string) } } -int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +int create_plugin(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance, BasicPluginBase** plugin_object) { if (MediaPluginGStreamer010::startup()) { - MediaPluginGStreamer010 *self = new MediaPluginGStreamer010(host_send_func, host_user_data); - *plugin_send_func = MediaPluginGStreamer010::staticReceiveMessage; - *plugin_user_data = (void*)self; - + *plugin_object = new MediaPluginGStreamer010(send_message_function, plugin_instance); return 0; // okay } else @@ -1234,15 +1351,14 @@ int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void class MediaPluginGStreamer010 : public MediaPluginBase { public: - MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance); ~MediaPluginGStreamer010(); /* virtual */ void receiveMessage(const char *message_string); }; MediaPluginGStreamer010::MediaPluginGStreamer010( - LLPluginInstance::sendMessageFunction host_send_func, - void *host_user_data ) : - MediaPluginBase(host_send_func, host_user_data) + LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance) : + MediaPluginBase(send_message_function, plugin_instance) { // no-op } @@ -1258,7 +1374,7 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string) } // We're building without GStreamer enabled. Just refuse to initialize. -int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +int create_plugin(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance, BasicPluginBase** plugin_object) { return -1; } diff --git a/indra/media_plugins/quicktime/CMakeLists.txt b/indra/plugins/quicktime/CMakeLists.txt old mode 100644 new mode 100755 similarity index 97% rename from indra/media_plugins/quicktime/CMakeLists.txt rename to indra/plugins/quicktime/CMakeLists.txt index df191f543..c827404c2 --- a/indra/media_plugins/quicktime/CMakeLists.txt +++ b/indra/plugins/quicktime/CMakeLists.txt @@ -30,7 +30,6 @@ if (DARWIN) find_library(CARBON_LIBRARY Carbon) endif (DARWIN) - ### media_plugin_quicktime set(media_plugin_quicktime_SOURCE_FILES @@ -77,7 +76,7 @@ if (QUICKTIME) PREFIX "" BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@executable_path" - LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp" + LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base_media/media_plugin_base.exp" ) # We use a bunch of deprecated system APIs. diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/plugins/quicktime/media_plugin_quicktime.cpp old mode 100644 new mode 100755 similarity index 95% rename from indra/media_plugins/quicktime/media_plugin_quicktime.cpp rename to indra/plugins/quicktime/media_plugin_quicktime.cpp index 1f516c0c5..a03cadf19 --- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp +++ b/indra/plugins/quicktime/media_plugin_quicktime.cpp @@ -40,10 +40,6 @@ #if defined(LL_DARWIN) #include #elif defined(LL_WINDOWS) - #undef __STDC_CONSTANT_MACROS //Needed, as boost/unordered_map.hpp already defines INT32_C, etc. - #if defined(_MSC_VER) && _MSC_VER >= 1600 - #define _STDINT_H //Visual Studio 2010 includes its own stdint header already - #endif #include "MacTypes.h" #include "QTML.h" #include "Movies.h" @@ -58,7 +54,7 @@ class MediaPluginQuickTime : public MediaPluginBase { public: - MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + MediaPluginQuickTime(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance); ~MediaPluginQuickTime(); /* virtual */ void receiveMessage(const char *message_string); @@ -768,9 +764,9 @@ private: }; MediaPluginQuickTime::MediaPluginQuickTime( - LLPluginInstance::sendMessageFunction host_send_func, - void *host_user_data ) : - MediaPluginBase(host_send_func, host_user_data), + LLPluginInstance::sendMessageFunction send_message_function, + LLPluginInstance* plugin_instance) : + MediaPluginBase(send_message_function, plugin_instance), mMinWidth( 0 ), mMaxWidth( 2048 ), mMinHeight( 0 ), @@ -1067,12 +1063,9 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string) }; } -int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +int create_plugin(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance, BasicPluginBase** plugin_object) { - MediaPluginQuickTime *self = new MediaPluginQuickTime(host_send_func, host_user_data); - *plugin_send_func = MediaPluginQuickTime::staticReceiveMessage; - *plugin_user_data = (void*)self; - + *plugin_object = new MediaPluginQuickTime(send_message_function, plugin_instance); return 0; } @@ -1083,15 +1076,15 @@ int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void class MediaPluginQuickTime : public MediaPluginBase { public: - MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + MediaPluginQuickTime(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance); ~MediaPluginQuickTime(); /* virtual */ void receiveMessage(const char *message_string); }; MediaPluginQuickTime::MediaPluginQuickTime( - LLPluginInstance::sendMessageFunction host_send_func, - void *host_user_data ) : - MediaPluginBase(host_send_func, host_user_data) + LLPluginInstance::sendMessageFunction send_message_function, + LLPluginInstance* plugin_instance) : + MediaPluginBase(send_message_function, plugin_instance) { // no-op } @@ -1107,7 +1100,7 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string) } // We're building without quicktime enabled. Just refuse to initialize. -int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +int create_plugin(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance, BasicPluginBase** plugin_object) { return -1; } diff --git a/indra/media_plugins/webkit/CMakeLists.txt b/indra/plugins/webkit/CMakeLists.txt similarity index 88% rename from indra/media_plugins/webkit/CMakeLists.txt rename to indra/plugins/webkit/CMakeLists.txt index 3b1f67954..1ffa2608a 100644 --- a/indra/media_plugins/webkit/CMakeLists.txt +++ b/indra/plugins/webkit/CMakeLists.txt @@ -30,17 +30,8 @@ include_directories( ${LLQTWEBKIT_INCLUDE_DIR} ) - ### media_plugin_webkit -if(NOT WORD_SIZE EQUAL 32) - if(WINDOWS) - add_definitions(/FIXED:NO) - else(WINDOWS) # not windows therefore gcc LINUX and DARWIN - add_definitions(-fPIC) - endif(WINDOWS) -endif(NOT WORD_SIZE EQUAL 32) - set(media_plugin_webkit_SOURCE_FILES media_plugin_webkit.cpp ) @@ -60,11 +51,9 @@ set(media_plugin_webkit_LINK_LIBRARIES # Select which VolumeCatcher implementation to use if (LINUX) - if (PULSEAUDIO_FOUND) + if (PULSEAUDIO) 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) + endif (PULSEAUDIO) list(APPEND media_plugin_webkit_LINK_LIBRARIES ${UI_LIBRARIES} # for glib/GTK ) @@ -78,6 +67,9 @@ elseif (DARWIN) ) elseif (WINDOWS) list(APPEND media_plugin_webkit_SOURCE_FILES windows_volume_catcher.cpp) +else (LINUX) + # All other platforms use the dummy volume catcher for now. + list(APPEND media_plugin_webkit_SOURCE_FILES dummy_volume_catcher.cpp) endif (LINUX) set_source_files_properties(${media_plugin_webkit_HEADER_FILES} @@ -114,7 +106,7 @@ if (DARWIN) PREFIX "" BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@executable_path" - LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp" + LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base_media/media_plugin_base.exp" ) # copy the webkit dylib to the build directory diff --git a/indra/plugins/webkit/dummy_volume_catcher.cpp b/indra/plugins/webkit/dummy_volume_catcher.cpp new file mode 100644 index 000000000..4df988789 --- /dev/null +++ b/indra/plugins/webkit/dummy_volume_catcher.cpp @@ -0,0 +1,65 @@ +/** + * @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=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/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/plugins/webkit/linux_volume_catcher.cpp similarity index 90% rename from indra/media_plugins/webkit/linux_volume_catcher.cpp rename to indra/plugins/webkit/linux_volume_catcher.cpp index 321d1f91f..cc3836ea5 100644 --- a/indra/media_plugins/webkit/linux_volume_catcher.cpp +++ b/indra/plugins/webkit/linux_volume_catcher.cpp @@ -3,26 +3,33 @@ * @brief A Linux-specific, PulseAudio-specific hack to detect and volume-adjust new audio sources * * @cond - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 * - * 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. + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception * - * 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. + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. * - * 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 + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ @@ -35,8 +42,9 @@ 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 //imprudence + #include "linden_common.h" -#include #include "volume_catcher.h" diff --git a/indra/plugins/webkit/linux_volume_catcher.h b/indra/plugins/webkit/linux_volume_catcher.h new file mode 100755 index 000000000..d4a1b38f9 --- /dev/null +++ b/indra/plugins/webkit/linux_volume_catcher.h @@ -0,0 +1,56 @@ +/** + * @file linux_volume_catcher.h + * @brief A Linux-specific, PulseAudio-specific hack to detect and volume-adjust new audio sources + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +#ifndef LINUX_VOLUME_CATCHER_H +#define LINUX_VOLUME_CATCHER_H + +#include "linden_common.h" + +class LinuxVolumeCatcherImpl; + +class LinuxVolumeCatcher +{ + public: + LinuxVolumeCatcher(); + ~LinuxVolumeCatcher(); + + void setVolume(F32 volume); // 0.0 - 1.0 + void pump(); // call this at least a few times a second if you can - it affects how quickly we can 'catch' a new audio source and adjust its volume + + private: + LinuxVolumeCatcherImpl *pimpl; +}; + +#endif // LINUX_VOLUME_CATCHER_H diff --git a/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc b/indra/plugins/webkit/linux_volume_catcher_pa_syms.inc similarity index 100% rename from indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc rename to indra/plugins/webkit/linux_volume_catcher_pa_syms.inc diff --git a/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc b/indra/plugins/webkit/linux_volume_catcher_paglib_syms.inc similarity index 100% rename from indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc rename to indra/plugins/webkit/linux_volume_catcher_paglib_syms.inc diff --git a/indra/media_plugins/webkit/mac_volume_catcher.cpp b/indra/plugins/webkit/mac_volume_catcher.cpp similarity index 85% rename from indra/media_plugins/webkit/mac_volume_catcher.cpp rename to indra/plugins/webkit/mac_volume_catcher.cpp index 8a06bb848..190823f73 100644 --- a/indra/media_plugins/webkit/mac_volume_catcher.cpp +++ b/indra/plugins/webkit/mac_volume_catcher.cpp @@ -3,26 +3,33 @@ * @brief A Mac OS X specific hack to control the volume level of all audio channels opened by a process. * * @cond - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 * - * 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. + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception * - * 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. + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. * - * 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 + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/plugins/webkit/media_plugin_webkit.cpp old mode 100644 new mode 100755 similarity index 93% rename from indra/media_plugins/webkit/media_plugin_webkit.cpp rename to indra/plugins/webkit/media_plugin_webkit.cpp index 4ae84e952..97920cf9f --- a/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/indra/plugins/webkit/media_plugin_webkit.cpp @@ -33,9 +33,10 @@ * @endcond */ +#include "linden_common.h" + #include "llqtwebkit.h" -#include "linden_common.h" #include "indra_constants.h" // for indra keyboard codes #include "llgl.h" @@ -44,6 +45,7 @@ #include "llpluginmessage.h" #include "llpluginmessageclasses.h" #include "media_plugin_base.h" +#include // set to 1 if you're using the version of llqtwebkit that's QPixmap-ified #if LL_LINUX @@ -64,7 +66,6 @@ extern "C" { # include # include #endif -#include #if LL_WINDOWS // *NOTE:Mani - This captures the module handle for the dll. This is used below @@ -78,6 +79,20 @@ extern "C" { } #endif +#ifdef LL_STANDALONE +#include +#elif defined(LL_LINUX) +// We don't provide Qt headers for non-standalone, therefore define this here. +// Our prebuilt is built with QT_NAMESPACE undefined. +#define QT_MANGLE_NAMESPACE(name) name +#define Q_INIT_RESOURCE(name) \ + do { extern int QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); \ + QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); } while (0) +#else +// Apparently this symbol doesn't exist in the windows and Mac tar balls provided by LL. +#define Q_INIT_RESOURCE(name) /*nothing*/ +#endif + //////////////////////////////////////////////////////////////////////////////// // class MediaPluginWebKit : @@ -85,7 +100,7 @@ class MediaPluginWebKit : public LLEmbeddedBrowserWindowObserver { public: - MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + MediaPluginWebKit(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance); ~MediaPluginWebKit(); /*virtual*/ void receiveMessage(const char *message_string); @@ -123,7 +138,6 @@ private: F32 mBackgroundR; F32 mBackgroundG; F32 mBackgroundB; - std::string mTarget; VolumeCatcher mVolumeCatcher; @@ -312,7 +326,11 @@ private: LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled ); // create single browser window - mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight, mTarget); +#if LLQTWEBKIT_API_VERSION >= 2 + mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow(mWidth, mHeight /*, mTarget*/ ); // We don't have mTarget yet. +#else + mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight ); +#endif // tell LLQtWebKit about the size of the browser window LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight ); @@ -322,6 +340,12 @@ private: // append details to agent string LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent ); + +// Viewer 2+ -- MC +#if LL_WINDOWS + // Set up window open behavior + LLQtWebKit::getInstance()->setWindowOpenBehavior(mBrowserWindowId, LLQtWebKit::WOB_SIMULATE_BLANK_HREF_CLICK); +#endif #if !LL_QTWEBKIT_USES_PIXMAPS // don't flip bitmap @@ -513,9 +537,16 @@ private: void onClickLinkHref(const EventType& event) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href"); +#if LLQTWEBKIT_API_VERSION >= 2 message.setValue("uri", event.getEventUri()); message.setValue("target", event.getStringValue()); message.setValue("uuid", event.getStringValue2()); +#else + // This will work as long as we don't need "uuid", which will be needed for MoaP. + message.setValue("uri", event.getStringValue()); + message.setValue("target", event.getStringValue2()); + message.setValueU32("target_type", event.getLinkType()); +#endif sendMessage(message); } @@ -524,10 +555,13 @@ private: void onClickLinkNoFollow(const EventType& event) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow"); +#if LLQTWEBKIT_API_VERSION >= 2 message.setValue("uri", event.getEventUri()); +#else + message.setValue("uri", event.getStringValue()); +#endif sendMessage(message); } - //////////////////////////////////////////////////////////////////////////////// // virtual @@ -540,42 +574,6 @@ private: // message.setValueBoolean("dead", (event.getIntValue() != 0)) 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(); - } LLQtWebKit::EKeyboardModifier decodeModifiers(std::string &modifiers) { @@ -721,31 +719,11 @@ private: } } - - 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) +MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance) : + MediaPluginBase(send_message_function, plugin_instance) { // std::cerr << "MediaPluginWebKit constructor" << std::endl; @@ -766,6 +744,9 @@ MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_ mJavascriptEnabled = true; // default to on mPluginsEnabled = true; // default to on mUserAgent = "LLPluginMedia Web Browser"; + + // Initialize WebCore resource. + Q_INIT_RESOURCE(WebCore); } MediaPluginWebKit::~MediaPluginWebKit() @@ -879,8 +860,6 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) { 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()) { @@ -1100,14 +1079,10 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_PASTE ); checkEditState(); } - if(message_name == "pick_file_response") - { - onPickFileResponse(message_in.getValue("file")); - } else { // std::cerr << "MediaPluginWebKit::receiveMessage: unknown media message: " << message_string << std::endl; - } + }; } else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) { @@ -1207,17 +1182,6 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) } } } - 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; @@ -1235,12 +1199,9 @@ 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) +int create_plugin(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance, BasicPluginBase** plugin_object) { - MediaPluginWebKit *self = new MediaPluginWebKit(host_send_func, host_user_data); - *plugin_send_func = MediaPluginWebKit::staticReceiveMessage; - *plugin_user_data = (void*)self; - + *plugin_object = new MediaPluginWebKit(send_message_function, plugin_instance); return 0; } diff --git a/indra/plugins/webkit/volume_catcher.h b/indra/plugins/webkit/volume_catcher.h new file mode 100644 index 000000000..855e99fc0 --- /dev/null +++ b/indra/plugins/webkit/volume_catcher.h @@ -0,0 +1,61 @@ +/** + * @file volume_catcher.h + * @brief Interface to a class with platform-specific implementations that allows control of the audio volume of all sources in the current process. + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +#ifndef VOLUME_CATCHER_H +#define VOLUME_CATCHER_H + +#include "linden_common.h" + +class VolumeCatcherImpl; + +class VolumeCatcher +{ + public: + VolumeCatcher(); + ~VolumeCatcher(); + + void setVolume(F32 volume); // 0.0 - 1.0 + + // Set the left-right pan of audio sources + // where -1.0 = left, 0 = center, and 1.0 = right + void setPan(F32 pan); + + void pump(); // call this at least a few times a second if you can - it affects how quickly we can 'catch' a new audio source and adjust its volume + + private: + VolumeCatcherImpl *pimpl; +}; + +#endif // VOLUME_CATCHER_H diff --git a/indra/media_plugins/webkit/windows_volume_catcher.cpp b/indra/plugins/webkit/windows_volume_catcher.cpp similarity index 61% rename from indra/media_plugins/webkit/windows_volume_catcher.cpp rename to indra/plugins/webkit/windows_volume_catcher.cpp index 46a7a3db6..64f70c419 100644 --- a/indra/media_plugins/webkit/windows_volume_catcher.cpp +++ b/indra/plugins/webkit/windows_volume_catcher.cpp @@ -3,30 +3,39 @@ * @brief A Windows implementation of volume level control of all audio channels opened by a process. * * @cond - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 * - * 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. + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception * - * 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. + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. * - * 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 + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ #include "volume_catcher.h" +# define WIN32_LEAN_AND_MEAN +# include #include #include "llmemory.h" class VolumeCatcherImpl : public LLSingleton