diff options
author | Andrey Lihatskiy <alihatskiy@productengine.com> | 2024-05-15 16:35:49 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-15 16:35:49 +0300 |
commit | e49dcb8d0c9f539997effb640e350d9d0689aae6 (patch) | |
tree | 1bf99eaccce6de17c62f13c6595f7f497548dc5c /indra/media_plugins | |
parent | 531cd34f670170ade57f8813fe48012b61a1d3c2 (diff) | |
parent | 5f8a7374b9f18e0112d6749a9c845bd077a81acb (diff) |
Merge pull request #1476 from secondlife/marchcat/x-b-merge
Maint X -> Maint B merge
Diffstat (limited to 'indra/media_plugins')
-rw-r--r-- | indra/media_plugins/base/media_plugin_base.cpp | 154 | ||||
-rw-r--r-- | indra/media_plugins/base/media_plugin_base.h | 118 | ||||
-rwxr-xr-x | indra/media_plugins/cef/linux_volume_catcher.cpp | 514 | ||||
-rw-r--r-- | indra/media_plugins/cef/mac_volume_catcher.cpp | 322 | ||||
-rw-r--r-- | indra/media_plugins/cef/mac_volume_catcher_null.cpp | 50 | ||||
-rw-r--r-- | indra/media_plugins/cef/media_plugin_cef.cpp | 1410 | ||||
-rw-r--r-- | indra/media_plugins/cef/volume_catcher.h | 30 | ||||
-rw-r--r-- | indra/media_plugins/cef/windows_volume_catcher.cpp | 62 | ||||
-rw-r--r-- | indra/media_plugins/example/media_plugin_example.cpp | 618 | ||||
-rw-r--r-- | indra/media_plugins/gstreamer10/llmediaimplgstreamer.h | 14 | ||||
-rw-r--r-- | indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 906 |
11 files changed, 2099 insertions, 2099 deletions
diff --git a/indra/media_plugins/base/media_plugin_base.cpp b/indra/media_plugins/base/media_plugin_base.cpp index dbbc973f00..3c603440df 100644 --- a/indra/media_plugins/base/media_plugin_base.cpp +++ b/indra/media_plugins/base/media_plugin_base.cpp @@ -1,28 +1,28 @@ -/** +/** * @file media_plugin_base.cpp * @brief Media plugin base class for LLMedia API plugin system * - * All plugins should be a subclass of MediaPluginBase. + * All plugins should be a subclass of MediaPluginBase. * * @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 @@ -40,102 +40,102 @@ /// @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 ) + LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data ) { - mHostSendFunction = host_send_func; - mHostUserData = host_user_data; - mDeleteMe = false; - mPixels = 0; - mWidth = 0; - mHeight = 0; - mTextureWidth = 0; - mTextureHeight = 0; - mDepth = 0; - mStatus = STATUS_NONE; + mHostSendFunction = host_send_func; + mHostUserData = host_user_data; + mDeleteMe = false; + mPixels = 0; + mWidth = 0; + mHeight = 0; + mTextureWidth = 0; + mTextureHeight = 0; + mDepth = 0; + mStatus = STATUS_NONE; } /** * Converts current media status enum value into string (STATUS_LOADING into "loading", etc.) - * + * * @return Media status string ("loading", "playing", "paused", etc) * */ std::string MediaPluginBase::statusString() { - std::string result; - - switch(mStatus) - { - case STATUS_LOADING: result = "loading"; break; - case STATUS_LOADED: result = "loaded"; break; - case STATUS_ERROR: result = "error"; break; - case STATUS_PLAYING: result = "playing"; break; - case STATUS_PAUSED: result = "paused"; break; - case STATUS_DONE: result = "done"; break; - default: - // keep the empty string - break; - } - - return result; + std::string result; + + switch(mStatus) + { + case STATUS_LOADING: result = "loading"; break; + case STATUS_LOADED: result = "loaded"; break; + case STATUS_ERROR: result = "error"; break; + case STATUS_PLAYING: result = "playing"; break; + case STATUS_PAUSED: result = "paused"; break; + case STATUS_DONE: result = "done"; break; + default: + // keep the empty string + break; + } + + return result; } - + /** * Set media status. - * + * * @param[in] status Media status (STATUS_LOADING, STATUS_PLAYING, STATUS_PAUSED, etc) * */ void MediaPluginBase::setStatus(EStatus status) { - if(mStatus != status) - { - mStatus = status; - sendStatus(); - } + if(mStatus != status) + { + mStatus = status; + sendStatus(); + } } /** * 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; - } - } + 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); + std::string output = message.generate(); + mHostSendFunction(output.c_str(), &mHostUserData); } /** * Notifies plugin loader shell that part of display area needs to be redrawn. - * + * * @param[in] left Left X coordinate of area to redraw (0,0 is at top left corner) * @param[in] top Top Y coordinate of area to redraw (0,0 is at top left corner) * @param[in] right Right X-coordinate of area to redraw (0,0 is at top left corner) @@ -144,27 +144,27 @@ void MediaPluginBase::sendMessage(const LLPluginMessage &message) */ void MediaPluginBase::setDirty(int left, int top, int right, int bottom) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated"); - - message.setValueS32("left", left); - message.setValueS32("top", top); - message.setValueS32("right", right); - message.setValueS32("bottom", bottom); - - sendMessage(message); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated"); + + message.setValueS32("left", left); + message.setValueS32("top", top); + message.setValueS32("right", right); + message.setValueS32("bottom", bottom); + + sendMessage(message); } /** * Sends "media_status" message to plugin loader shell ("loading", "playing", "paused", etc.) - * + * */ void MediaPluginBase::sendStatus() { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "media_status"); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "media_status"); + + message.setValue("status", statusString()); - message.setValue("status", statusString()); - - sendMessage(message); + sendMessage(message); } #if LL_LINUX @@ -228,12 +228,12 @@ void SymbolGrabber::ungrabSymbols() extern "C" { - LLSYMEXPORT int LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data); + 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 @@ -245,12 +245,12 @@ extern "C" 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); + 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 ) { - return 1; + return 1; } #endif diff --git a/indra/media_plugins/base/media_plugin_base.h b/indra/media_plugins/base/media_plugin_base.h index 2e975a5bf2..d5cb5ac550 100644 --- a/indra/media_plugins/base/media_plugin_base.h +++ b/indra/media_plugins/base/media_plugin_base.h @@ -1,4 +1,4 @@ -/** +/** * @file media_plugin_base.h * @brief Media plugin base class for LLMedia API plugin system * @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ * @endcond @@ -64,93 +64,93 @@ extern SymbolGrabber gSymbolGrabber; class MediaPluginBase { public: - MediaPluginBase(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + MediaPluginBase(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); /** Media plugin destructor. */ - virtual ~MediaPluginBase() {} + 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); + virtual void receiveMessage(const char *message_string) = 0; + + static void staticReceiveMessage(const char *message_string, void **user_data); protected: /** Plugin status. */ - typedef enum - { - STATUS_NONE, - STATUS_LOADING, - STATUS_LOADED, - STATUS_ERROR, - STATUS_PLAYING, - STATUS_PAUSED, - STATUS_DONE - } EStatus; + typedef enum + { + STATUS_NONE, + STATUS_LOADING, + STATUS_LOADED, + STATUS_ERROR, + STATUS_PLAYING, + STATUS_PAUSED, + STATUS_DONE + } EStatus; /** Plugin shared memory. */ - class SharedSegmentInfo - { - public: + class SharedSegmentInfo + { + public: /** Shared memory address. */ - void *mAddress; + void *mAddress; /** Shared memory size. */ - size_t mSize; - }; + size_t mSize; + }; + + void sendMessage(const LLPluginMessage &message); + void sendStatus(); + std::string statusString(); + void setStatus(EStatus status); - void sendMessage(const LLPluginMessage &message); - void sendStatus(); - std::string statusString(); - void setStatus(EStatus status); - - /// Note: The quicktime plugin overrides this to add current time and duration to the message. - virtual void setDirty(int left, int top, int right, int bottom); + /// Note: The quicktime plugin overrides this to add current time and duration to the message. + virtual void setDirty(int left, int top, int right, int bottom); /** Map of shared memory names to shared memory. */ - typedef std::map<std::string, SharedSegmentInfo> SharedSegmentMap; + typedef std::map<std::string, SharedSegmentInfo> SharedSegmentMap; + - /** Function to send message from plugin to plugin loader shell. */ - LLPluginInstance::sendMessageFunction mHostSendFunction; + LLPluginInstance::sendMessageFunction mHostSendFunction; /** Message data being sent to plugin loader shell by mHostSendFunction. */ - void *mHostUserData; + void *mHostUserData; /** Flag to delete plugin instance (self). */ - bool mDeleteMe; + 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; + 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 */ - std::string mTextureSegmentName; + std::string mTextureSegmentName; /** Width of plugin display in pixels. */ - int mWidth; + int mWidth; /** Height of plugin display in pixels. */ - int mHeight; + int mHeight; /** Width of plugin texture. */ - int mTextureWidth; + int mTextureWidth; /** Height of plugin texture. */ - int mTextureHeight; + int mTextureHeight; /** Pixel depth (pixel size in bytes). */ - int mDepth; + int mDepth; /** Current status of plugin. */ - EStatus mStatus; + EStatus mStatus; /** Map of shared memory segments. */ - SharedSegmentMap mSharedSegments; + SharedSegmentMap mSharedSegments; }; /** The plugin <b>must</b> define this function to create its instance. - * It should look something like this: + * 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; - * } + * { + * 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); + LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data, + LLPluginInstance::sendMessageFunction *plugin_send_func, + void **plugin_user_data); diff --git a/indra/media_plugins/cef/linux_volume_catcher.cpp b/indra/media_plugins/cef/linux_volume_catcher.cpp index 9e6fe461a6..982b79f5b3 100755 --- a/indra/media_plugins/cef/linux_volume_catcher.cpp +++ b/indra/media_plugins/cef/linux_volume_catcher.cpp @@ -1,4 +1,4 @@ -/** +/** * @file linux_volume_catcher.cpp * @brief A Linux-specific, PulseAudio-specific hack to detect and volume-adjust new audio sources * @@ -6,21 +6,21 @@ * $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 @@ -64,361 +64,361 @@ SymbolGrabber gSymbolGrabber; // PulseAudio requires a chain of callbacks with C linkage extern "C" { - void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *i, int eol, void *userdata); - void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata); - void callback_context_state(pa_context *context, void *userdata); + void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *i, int eol, void *userdata); + void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata); + void callback_context_state(pa_context *context, void *userdata); } class VolumeCatcherImpl { public: - VolumeCatcherImpl(); - ~VolumeCatcherImpl(); + VolumeCatcherImpl(); + ~VolumeCatcherImpl(); - void setVolume(F32 volume); - void pump(void); + void setVolume(F32 volume); + void pump(void); - // for internal use - can't be private because used from our C callbacks + // for internal use - can't be private because used from our C callbacks - bool loadsyms(std::string pulse_dso_name); - void init(); - void cleanup(); + bool loadsyms(std::string pulse_dso_name); + void init(); + void cleanup(); - void update_all_volumes(F32 volume); - void update_index_volume(U32 index, F32 volume); - void connected_okay(); + void update_all_volumes(F32 volume); + void update_index_volume(U32 index, F32 volume); + void connected_okay(); - std::set<U32> mSinkInputIndices; - std::map<U32,U32> mSinkInputNumChannels; - F32 mDesiredVolume; - pa_glib_mainloop *mMainloop; - pa_context *mPAContext; - bool mConnected; - bool mGotSyms; + std::set<U32> mSinkInputIndices; + std::map<U32,U32> mSinkInputNumChannels; + F32 mDesiredVolume; + pa_glib_mainloop *mMainloop; + pa_context *mPAContext; + bool mConnected; + bool mGotSyms; }; VolumeCatcherImpl::VolumeCatcherImpl() - : mDesiredVolume(0.0f), - mMainloop(nullptr), - mPAContext(nullptr), - mConnected(false), - mGotSyms(false) + : mDesiredVolume(0.0f), + mMainloop(nullptr), + mPAContext(nullptr), + mConnected(false), + mGotSyms(false) { - init(); + init(); } VolumeCatcherImpl::~VolumeCatcherImpl() { - cleanup(); + cleanup(); } bool VolumeCatcherImpl::loadsyms(std::string pulse_dso_name) { - //return grab_pa_syms({pulse_dso_name}); + //return grab_pa_syms({pulse_dso_name}); return gSymbolGrabber.grabSymbols( { pulse_dso_name }) ; } void VolumeCatcherImpl::init() { - // try to be as defensive as possible because PA's interface is a - // bit fragile and (for our purposes) we'd rather simply not function - // than crash - - // we cheat and rely upon libpulse-mainloop-glib.so.0 to pull-in - // libpulse.so.0 - this isn't a great assumption, and the two DSOs should - // probably be loaded separately. Our Linux DSO framework needs refactoring, - // we do this sort of thing a lot with practically identical logic... - mGotSyms = loadsyms("libpulse-mainloop-glib.so.0"); - if (!mGotSyms) return; - - mMainloop = llpa_glib_mainloop_new(g_main_context_default()); - - if (mMainloop) - { - pa_mainloop_api *api = llpa_glib_mainloop_get_api(mMainloop); - - if (api) - { - pa_proplist *proplist = llpa_proplist_new(); - - if (proplist) - { - llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ICON_NAME, "multimedia-player"); - llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ID, "com.secondlife.viewer.mediaplugvoladjust"); - llpa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "SL Plugin Volume Adjuster"); - llpa_proplist_sets(proplist, PA_PROP_APPLICATION_VERSION, "1"); - - // plain old pa_context_new() is broken! - mPAContext = llpa_context_new_with_proplist(api, nullptr, proplist); - - llpa_proplist_free(proplist); - } - } - } - - // Now we've set up a PA context and mainloop, try connecting the - // PA context to a PA daemon. - if (mPAContext) - { - llpa_context_set_state_callback(mPAContext, callback_context_state, this); - pa_context_flags_t cflags = (pa_context_flags)0; // maybe add PA_CONTEXT_NOAUTOSPAWN? - if (llpa_context_connect(mPAContext, nullptr, cflags, nullptr) >= 0) - { - // Okay! We haven't definitely connected, but we - // haven't definitely failed yet. - } - else - { - // Failed to connect to PA manager... we'll leave - // things like that. Perhaps we should try again later. - } - } + // try to be as defensive as possible because PA's interface is a + // bit fragile and (for our purposes) we'd rather simply not function + // than crash + + // we cheat and rely upon libpulse-mainloop-glib.so.0 to pull-in + // libpulse.so.0 - this isn't a great assumption, and the two DSOs should + // probably be loaded separately. Our Linux DSO framework needs refactoring, + // we do this sort of thing a lot with practically identical logic... + mGotSyms = loadsyms("libpulse-mainloop-glib.so.0"); + if (!mGotSyms) return; + + mMainloop = llpa_glib_mainloop_new(g_main_context_default()); + + if (mMainloop) + { + pa_mainloop_api *api = llpa_glib_mainloop_get_api(mMainloop); + + if (api) + { + pa_proplist *proplist = llpa_proplist_new(); + + if (proplist) + { + llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ICON_NAME, "multimedia-player"); + llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ID, "com.secondlife.viewer.mediaplugvoladjust"); + llpa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "SL Plugin Volume Adjuster"); + llpa_proplist_sets(proplist, PA_PROP_APPLICATION_VERSION, "1"); + + // plain old pa_context_new() is broken! + mPAContext = llpa_context_new_with_proplist(api, nullptr, proplist); + + llpa_proplist_free(proplist); + } + } + } + + // Now we've set up a PA context and mainloop, try connecting the + // PA context to a PA daemon. + if (mPAContext) + { + llpa_context_set_state_callback(mPAContext, callback_context_state, this); + pa_context_flags_t cflags = (pa_context_flags)0; // maybe add PA_CONTEXT_NOAUTOSPAWN? + if (llpa_context_connect(mPAContext, nullptr, cflags, nullptr) >= 0) + { + // Okay! We haven't definitely connected, but we + // haven't definitely failed yet. + } + else + { + // Failed to connect to PA manager... we'll leave + // things like that. Perhaps we should try again later. + } + } } void VolumeCatcherImpl::cleanup() { - mConnected = false; + mConnected = false; - if (mGotSyms && mPAContext) - { - llpa_context_disconnect(mPAContext); - llpa_context_unref(mPAContext); - } + if (mGotSyms && mPAContext) + { + llpa_context_disconnect(mPAContext); + llpa_context_unref(mPAContext); + } - mPAContext = nullptr; + mPAContext = nullptr; - if (mGotSyms && mMainloop) - llpa_glib_mainloop_free(mMainloop); + if (mGotSyms && mMainloop) + llpa_glib_mainloop_free(mMainloop); - mMainloop = nullptr; + mMainloop = nullptr; } void VolumeCatcherImpl::setVolume(F32 volume) { - mDesiredVolume = volume; - - if (!mGotSyms) return; + mDesiredVolume = volume; + + if (!mGotSyms) return; - if (mConnected && mPAContext) - { - update_all_volumes(mDesiredVolume); - } + if (mConnected && mPAContext) + { + update_all_volumes(mDesiredVolume); + } - pump(); + pump(); } void VolumeCatcherImpl::pump() { - gboolean may_block = FALSE; - g_main_context_iteration(g_main_context_default(), may_block); + gboolean may_block = FALSE; + g_main_context_iteration(g_main_context_default(), may_block); } void VolumeCatcherImpl::connected_okay() { - pa_operation *op; - - // fetch global list of existing sinkinputs - if ((op = llpa_context_get_sink_input_info_list(mPAContext, - callback_discovered_sinkinput, - this))) - { - llpa_operation_unref(op); - } - - // subscribe to future global sinkinput changes - llpa_context_set_subscribe_callback(mPAContext, - callback_subscription_alert, - this); - if ((op = llpa_context_subscribe(mPAContext, (pa_subscription_mask_t) - (PA_SUBSCRIPTION_MASK_SINK_INPUT), + pa_operation *op; + + // fetch global list of existing sinkinputs + if ((op = llpa_context_get_sink_input_info_list(mPAContext, + callback_discovered_sinkinput, + this))) + { + llpa_operation_unref(op); + } + + // subscribe to future global sinkinput changes + llpa_context_set_subscribe_callback(mPAContext, + callback_subscription_alert, + this); + if ((op = llpa_context_subscribe(mPAContext, (pa_subscription_mask_t) + (PA_SUBSCRIPTION_MASK_SINK_INPUT), nullptr, nullptr))) - { - llpa_operation_unref(op); - } + { + llpa_operation_unref(op); + } } void VolumeCatcherImpl::update_all_volumes(F32 volume) { - for (std::set<U32>::iterator it = mSinkInputIndices.begin(); - it != mSinkInputIndices.end(); ++it) - { - update_index_volume(*it, volume); - } + for (std::set<U32>::iterator it = mSinkInputIndices.begin(); + it != mSinkInputIndices.end(); ++it) + { + update_index_volume(*it, volume); + } } void VolumeCatcherImpl::update_index_volume(U32 index, F32 volume) { - static pa_cvolume cvol; - llpa_cvolume_set(&cvol, mSinkInputNumChannels[index], - llpa_sw_volume_from_linear(volume)); - - pa_context *c = mPAContext; - uint32_t idx = index; - const pa_cvolume *cvolumep = &cvol; - pa_context_success_cb_t cb = nullptr; // okay as null - void *userdata = nullptr; // okay as null - - pa_operation *op; - if ((op = llpa_context_set_sink_input_volume(c, idx, cvolumep, cb, userdata))) - llpa_operation_unref(op); + static pa_cvolume cvol; + llpa_cvolume_set(&cvol, mSinkInputNumChannels[index], + llpa_sw_volume_from_linear(volume)); + + pa_context *c = mPAContext; + uint32_t idx = index; + const pa_cvolume *cvolumep = &cvol; + pa_context_success_cb_t cb = nullptr; // okay as null + void *userdata = nullptr; // okay as null + + pa_operation *op; + if ((op = llpa_context_set_sink_input_volume(c, idx, cvolumep, cb, userdata))) + llpa_operation_unref(op); } pid_t getParentPid( pid_t aPid ) { - std::stringstream strm; - strm << "/proc/" << aPid << "/status"; - std::ifstream in{ strm.str() }; - - if( !in.is_open() ) - return 0; - - pid_t res {0}; - while( !in.eof() && res == 0 ) - { - std::string line; - line.resize( 1024, 0 ); - in.getline( &line[0], line.length() ); - - auto i = line.find( "PPid:" ); - - if( i == std::string::npos ) - continue; - - char const *pIn = line.c_str() + 5; // Skip over pid; - while( *pIn != 0 && isspace( *pIn ) ) - ++pIn; - - if( *pIn ) - res = atoll( pIn ); - } - return res; + std::stringstream strm; + strm << "/proc/" << aPid << "/status"; + std::ifstream in{ strm.str() }; + + if( !in.is_open() ) + return 0; + + pid_t res {0}; + while( !in.eof() && res == 0 ) + { + std::string line; + line.resize( 1024, 0 ); + in.getline( &line[0], line.length() ); + + auto i = line.find( "PPid:" ); + + if( i == std::string::npos ) + continue; + + char const *pIn = line.c_str() + 5; // Skip over pid; + while( *pIn != 0 && isspace( *pIn ) ) + ++pIn; + + if( *pIn ) + res = atoll( pIn ); + } + return res; } bool isPluginPid( pid_t aPid ) { - auto myPid = getpid(); + auto myPid = getpid(); - do - { - if( aPid == myPid ) - return true; - aPid = getParentPid( aPid ); - } while( aPid > 1 ); + do + { + if( aPid == myPid ) + return true; + aPid = getParentPid( aPid ); + } while( aPid > 1 ); - return false; + return false; } void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *sii, int eol, void *userdata) { - VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata); - llassert(impl); - - if (0 == eol) - { - pa_proplist *proplist = sii->proplist; - pid_t sinkpid = atoll(llpa_proplist_gets(proplist, PA_PROP_APPLICATION_PROCESS_ID)); - - if (isPluginPid( sinkpid )) // does the discovered sinkinput belong to this process? - { - bool is_new = (impl->mSinkInputIndices.find(sii->index) == impl->mSinkInputIndices.end()); - - impl->mSinkInputIndices.insert(sii->index); - impl->mSinkInputNumChannels[sii->index] = sii->channel_map.channels; - - if (is_new) - { - // new! - impl->update_index_volume(sii->index, impl->mDesiredVolume); - } - else - { - // seen it already, do nothing. - } - } - } + VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata); + llassert(impl); + + if (0 == eol) + { + pa_proplist *proplist = sii->proplist; + pid_t sinkpid = atoll(llpa_proplist_gets(proplist, PA_PROP_APPLICATION_PROCESS_ID)); + + if (isPluginPid( sinkpid )) // does the discovered sinkinput belong to this process? + { + bool is_new = (impl->mSinkInputIndices.find(sii->index) == impl->mSinkInputIndices.end()); + + impl->mSinkInputIndices.insert(sii->index); + impl->mSinkInputNumChannels[sii->index] = sii->channel_map.channels; + + if (is_new) + { + // new! + impl->update_index_volume(sii->index, impl->mDesiredVolume); + } + else + { + // seen it already, do nothing. + } + } + } } void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata) { - VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata); - llassert(impl); + VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata); + llassert(impl); - switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) - { + switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) + { case PA_SUBSCRIPTION_EVENT_SINK_INPUT: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) - { - // forget this sinkinput, if we were caring about it - impl->mSinkInputIndices.erase(index); - impl->mSinkInputNumChannels.erase(index); - } - else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) - { - // ask for more info about this new sinkinput - pa_operation *op; - if ((op = llpa_context_get_sink_input_info(impl->mPAContext, index, callback_discovered_sinkinput, impl))) - { - llpa_operation_unref(op); - } - } - else - { - // property change on this sinkinput - we don't care. - } - break; - - default:; - } + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) + { + // forget this sinkinput, if we were caring about it + impl->mSinkInputIndices.erase(index); + impl->mSinkInputNumChannels.erase(index); + } + else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) + { + // ask for more info about this new sinkinput + pa_operation *op; + if ((op = llpa_context_get_sink_input_info(impl->mPAContext, index, callback_discovered_sinkinput, impl))) + { + llpa_operation_unref(op); + } + } + else + { + // property change on this sinkinput - we don't care. + } + break; + + default:; + } } void callback_context_state(pa_context *context, void *userdata) { - VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata); - llassert(impl); - - switch (llpa_context_get_state(context)) - { - case PA_CONTEXT_READY: - impl->mConnected = true; - impl->connected_okay(); - break; - case PA_CONTEXT_TERMINATED: - impl->mConnected = false; - break; - case PA_CONTEXT_FAILED: - impl->mConnected = false; - break; - default:; - } + VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata); + llassert(impl); + + switch (llpa_context_get_state(context)) + { + case PA_CONTEXT_READY: + impl->mConnected = true; + impl->connected_okay(); + break; + case PA_CONTEXT_TERMINATED: + impl->mConnected = false; + break; + case PA_CONTEXT_FAILED: + impl->mConnected = false; + break; + default:; + } } ///////////////////////////////////////////////////// VolumeCatcher::VolumeCatcher() { - pimpl = new VolumeCatcherImpl(); + pimpl = new VolumeCatcherImpl(); } VolumeCatcher::~VolumeCatcher() { - delete pimpl; - pimpl = nullptr; + delete pimpl; + pimpl = nullptr; } void VolumeCatcher::setVolume(F32 volume) { - llassert(pimpl); - pimpl->setVolume(volume); + llassert(pimpl); + pimpl->setVolume(volume); } void VolumeCatcher::setPan(F32 pan) { - // TODO: implement this (if possible) + // TODO: implement this (if possible) } void VolumeCatcher::pump() { - llassert(pimpl); - pimpl->pump(); + llassert(pimpl); + pimpl->pump(); } diff --git a/indra/media_plugins/cef/mac_volume_catcher.cpp b/indra/media_plugins/cef/mac_volume_catcher.cpp index dddb9c2077..32251c0999 100644 --- a/indra/media_plugins/cef/mac_volume_catcher.cpp +++ b/indra/media_plugins/cef/mac_volume_catcher.cpp @@ -1,4 +1,4 @@ -/** +/** * @file mac_volume_catcher.cpp * @brief A Mac OS X specific hack to control the volume level of all audio channels opened by a process. * @@ -11,26 +11,26 @@ * 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 */ /************************************************************************************************************** - This code works by using CaptureComponent to capture the "Default Output" audio component - (kAudioUnitType_Output/kAudioUnitSubType_DefaultOutput) and delegating all calls to the original component. - It does this just to keep track of all instances of the default output component, so that it can set the - kHALOutputParam_Volume parameter on all of them to adjust the output volume. + This code works by using CaptureComponent to capture the "Default Output" audio component + (kAudioUnitType_Output/kAudioUnitSubType_DefaultOutput) and delegating all calls to the original component. + It does this just to keep track of all instances of the default output component, so that it can set the + kHALOutputParam_Volume parameter on all of them to adjust the output volume. **************************************************************************************************************/ #include "volume_catcher.h" @@ -49,35 +49,35 @@ class VolumeCatcherImpl { public: - void setVolume(F32 volume); - void setPan(F32 pan); - - void setInstanceVolume(VolumeCatcherStorage *instance); - - std::list<VolumeCatcherStorage*> mComponentInstances; - Component mOriginalDefaultOutput; - Component mVolumeAdjuster; - - static VolumeCatcherImpl *getInstance(); + void setVolume(F32 volume); + void setPan(F32 pan); + + void setInstanceVolume(VolumeCatcherStorage *instance); + + std::list<VolumeCatcherStorage*> mComponentInstances; + Component mOriginalDefaultOutput; + Component mVolumeAdjuster; + + static VolumeCatcherImpl *getInstance(); private: - // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. - VolumeCatcherImpl(); - static VolumeCatcherImpl *sInstance; - - // The singlar instance of this class is expected to last until the process exits. - // To ensure this, we declare the destructor here but never define it, so any code which attempts to destroy the instance will not link. - ~VolumeCatcherImpl(); - - F32 mVolume; - F32 mPan; + // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. + VolumeCatcherImpl(); + static VolumeCatcherImpl *sInstance; + + // The singlar instance of this class is expected to last until the process exits. + // To ensure this, we declare the destructor here but never define it, so any code which attempts to destroy the instance will not link. + ~VolumeCatcherImpl(); + + F32 mVolume; + F32 mPan; }; VolumeCatcherImpl *VolumeCatcherImpl::sInstance = NULL;; struct VolumeCatcherStorage { - ComponentInstance self; - ComponentInstance delegate; + ComponentInstance self; + ComponentInstance delegate; }; static ComponentResult volume_catcher_component_entry(ComponentParameters *cp, Handle componentStorage); @@ -86,188 +86,188 @@ static ComponentResult volume_catcher_component_close(VolumeCatcherStorage *stor VolumeCatcherImpl *VolumeCatcherImpl::getInstance() { - if(!sInstance) - { - sInstance = new VolumeCatcherImpl; - } - - return sInstance; + if(!sInstance) + { + sInstance = new VolumeCatcherImpl; + } + + return sInstance; } VolumeCatcherImpl::VolumeCatcherImpl() { - mVolume = 1.0; // default to full volume - mPan = 0.0; // and center pan - - ComponentDescription desc; - desc.componentType = kAudioUnitType_Output; - desc.componentSubType = kAudioUnitSubType_DefaultOutput; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; - - // Find the original default output component - mOriginalDefaultOutput = FindNextComponent(NULL, &desc); - - // Register our own output component with the same parameters - mVolumeAdjuster = RegisterComponent(&desc, NewComponentRoutineUPP(volume_catcher_component_entry), 0, NULL, NULL, NULL); - - // Capture the original component, so we always get found instead. - CaptureComponent(mOriginalDefaultOutput, mVolumeAdjuster); + mVolume = 1.0; // default to full volume + mPan = 0.0; // and center pan + + ComponentDescription desc; + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_DefaultOutput; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + // Find the original default output component + mOriginalDefaultOutput = FindNextComponent(NULL, &desc); + + // Register our own output component with the same parameters + mVolumeAdjuster = RegisterComponent(&desc, NewComponentRoutineUPP(volume_catcher_component_entry), 0, NULL, NULL, NULL); + + // Capture the original component, so we always get found instead. + CaptureComponent(mOriginalDefaultOutput, mVolumeAdjuster); } static ComponentResult volume_catcher_component_entry(ComponentParameters *cp, Handle componentStorage) { - ComponentResult result = badComponentSelector; - VolumeCatcherStorage *storage = (VolumeCatcherStorage*)componentStorage; - - switch(cp->what) - { - case kComponentOpenSelect: -// std::cerr << "kComponentOpenSelect" << std::endl; - result = CallComponentFunctionWithStorageProcInfo((Handle)storage, cp, (ProcPtr)volume_catcher_component_open, uppCallComponentOpenProcInfo); - break; - - case kComponentCloseSelect: -// std::cerr << "kComponentCloseSelect" << std::endl; - result = CallComponentFunctionWithStorageProcInfo((Handle)storage, cp, (ProcPtr)volume_catcher_component_close, uppCallComponentCloseProcInfo); - // CallComponentFunctionWithStorageProcInfo - break; - - default: -// std::cerr << "Delegating selector: " << cp->what << " to component instance " << storage->delegate << std::endl; - result = DelegateComponentCall(cp, storage->delegate); - break; - } - - return result; + ComponentResult result = badComponentSelector; + VolumeCatcherStorage *storage = (VolumeCatcherStorage*)componentStorage; + + switch(cp->what) + { + case kComponentOpenSelect: +// std::cerr << "kComponentOpenSelect" << std::endl; + result = CallComponentFunctionWithStorageProcInfo((Handle)storage, cp, (ProcPtr)volume_catcher_component_open, uppCallComponentOpenProcInfo); + break; + + case kComponentCloseSelect: +// std::cerr << "kComponentCloseSelect" << std::endl; + result = CallComponentFunctionWithStorageProcInfo((Handle)storage, cp, (ProcPtr)volume_catcher_component_close, uppCallComponentCloseProcInfo); + // CallComponentFunctionWithStorageProcInfo + break; + + default: +// std::cerr << "Delegating selector: " << cp->what << " to component instance " << storage->delegate << std::endl; + result = DelegateComponentCall(cp, storage->delegate); + break; + } + + return result; } static ComponentResult volume_catcher_component_open(VolumeCatcherStorage *storage, ComponentInstance self) { - ComponentResult result = noErr; - VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); - - storage = new VolumeCatcherStorage; - - storage->self = self; - storage->delegate = NULL; - - result = OpenAComponent(impl->mOriginalDefaultOutput, &(storage->delegate)); - - if(result != noErr) - { -// std::cerr << "OpenAComponent result = " << result << ", component ref = " << storage->delegate << std::endl; - - // If we failed to open the delagate component, our open is going to fail. Clean things up. - delete storage; - } - else - { - // Success -- set up this component's storage - SetComponentInstanceStorage(self, (Handle)storage); - - // add this instance to the global list - impl->mComponentInstances.push_back(storage); - - // and set up the initial volume - impl->setInstanceVolume(storage); - } - - return result; + ComponentResult result = noErr; + VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); + + storage = new VolumeCatcherStorage; + + storage->self = self; + storage->delegate = NULL; + + result = OpenAComponent(impl->mOriginalDefaultOutput, &(storage->delegate)); + + if(result != noErr) + { +// std::cerr << "OpenAComponent result = " << result << ", component ref = " << storage->delegate << std::endl; + + // If we failed to open the delagate component, our open is going to fail. Clean things up. + delete storage; + } + else + { + // Success -- set up this component's storage + SetComponentInstanceStorage(self, (Handle)storage); + + // add this instance to the global list + impl->mComponentInstances.push_back(storage); + + // and set up the initial volume + impl->setInstanceVolume(storage); + } + + return result; } static ComponentResult volume_catcher_component_close(VolumeCatcherStorage *storage, ComponentInstance self) { - ComponentResult result = noErr; - - if(storage) - { - if(storage->delegate) - { - CloseComponent(storage->delegate); - storage->delegate = NULL; - } - - VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); - impl->mComponentInstances.remove(storage); - delete[] storage; - } - - return result; + ComponentResult result = noErr; + + if(storage) + { + if(storage->delegate) + { + CloseComponent(storage->delegate); + storage->delegate = NULL; + } + + VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); + impl->mComponentInstances.remove(storage); + delete[] storage; + } + + return result; } void VolumeCatcherImpl::setVolume(F32 volume) { - VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); - impl->mVolume = volume; - - // Iterate through all known instances, setting the volume on each. - for(std::list<VolumeCatcherStorage*>::iterator iter = mComponentInstances.begin(); iter != mComponentInstances.end(); ++iter) - { - impl->setInstanceVolume(*iter); - } + VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); + impl->mVolume = volume; + + // Iterate through all known instances, setting the volume on each. + for(std::list<VolumeCatcherStorage*>::iterator iter = mComponentInstances.begin(); iter != mComponentInstances.end(); ++iter) + { + impl->setInstanceVolume(*iter); + } } void VolumeCatcherImpl::setPan(F32 pan) { - VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); - impl->mPan = pan; - - // TODO: implement this. - // This will probably require adding a "panner" audio unit to the chain somehow. - // There's also a "3d mixer" component that we might be able to use... + VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); + impl->mPan = pan; + + // TODO: implement this. + // This will probably require adding a "panner" audio unit to the chain somehow. + // There's also a "3d mixer" component that we might be able to use... } void VolumeCatcherImpl::setInstanceVolume(VolumeCatcherStorage *instance) { -// std::cerr << "Setting volume on component instance: " << (instance->delegate) << " to " << mVolume << std::endl; - - OSStatus err = noErr; - - if(instance && instance->delegate) - { - err = AudioUnitSetParameter( - instance->delegate, - kHALOutputParam_Volume, - kAudioUnitScope_Global, - 0, - mVolume, - 0); - } - - if(err) - { -// std::cerr << " AudioUnitSetParameter returned " << err << std::endl; - } +// std::cerr << "Setting volume on component instance: " << (instance->delegate) << " to " << mVolume << std::endl; + + OSStatus err = noErr; + + if(instance && instance->delegate) + { + err = AudioUnitSetParameter( + instance->delegate, + kHALOutputParam_Volume, + kAudioUnitScope_Global, + 0, + mVolume, + 0); + } + + if(err) + { +// std::cerr << " AudioUnitSetParameter returned " << err << std::endl; + } } ///////////////////////////////////////////////////// VolumeCatcher::VolumeCatcher() { - pimpl = VolumeCatcherImpl::getInstance(); + pimpl = VolumeCatcherImpl::getInstance(); } VolumeCatcher::~VolumeCatcher() { - // Let the instance persist until exit. + // Let the instance persist until exit. } void VolumeCatcher::setVolume(F32 volume) { - pimpl->setVolume(volume); + pimpl->setVolume(volume); } void VolumeCatcher::setPan(F32 pan) { - pimpl->setPan(pan); + pimpl->setPan(pan); } void VolumeCatcher::pump() { - // No periodic tasks are necessary for this implementation. + // No periodic tasks are necessary for this implementation. } #if LL_DARWIN diff --git a/indra/media_plugins/cef/mac_volume_catcher_null.cpp b/indra/media_plugins/cef/mac_volume_catcher_null.cpp index f4fcef71aa..c479e24a95 100644 --- a/indra/media_plugins/cef/mac_volume_catcher_null.cpp +++ b/indra/media_plugins/cef/mac_volume_catcher_null.cpp @@ -1,28 +1,28 @@ -/** +/** * @file windows_volume_catcher.cpp * @brief A null implementation of volume level control of all audio channels opened by a process. - * We are using this for the macOS version for now until we can understand how to make the + * We are using this for the macOS version for now until we can understand how to make the * exitising mac_volume_catcher.cpp work without the (now, non-existant) QuickTime dependency * * @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 @@ -32,24 +32,24 @@ #include "llsingleton.h" class VolumeCatcherImpl : public LLSingleton<VolumeCatcherImpl> { - LLSINGLETON(VolumeCatcherImpl); - // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. - ~VolumeCatcherImpl(); + LLSINGLETON(VolumeCatcherImpl); + // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. + ~VolumeCatcherImpl(); public: - void setVolume(F32 volume); - void setPan(F32 pan); - + void setVolume(F32 volume); + void setPan(F32 pan); + private: - F32 mVolume; - F32 mPan; - bool mSystemIsVistaOrHigher; + F32 mVolume; + F32 mPan; + bool mSystemIsVistaOrHigher; }; VolumeCatcherImpl::VolumeCatcherImpl() -: mVolume(1.0f), // default volume is max - mPan(0.f) // default pan is centered +: mVolume(1.0f), // default volume is max + mPan(0.f) // default pan is centered { } @@ -59,37 +59,37 @@ VolumeCatcherImpl::~VolumeCatcherImpl() void VolumeCatcherImpl::setVolume(F32 volume) { - mVolume = volume; + mVolume = volume; } void VolumeCatcherImpl::setPan(F32 pan) -{ // remember pan for calculating individual channel levels later - mPan = pan; +{ // remember pan for calculating individual channel levels later + mPan = pan; } ///////////////////////////////////////////////////// VolumeCatcher::VolumeCatcher() { - pimpl = VolumeCatcherImpl::getInstance(); + pimpl = VolumeCatcherImpl::getInstance(); } VolumeCatcher::~VolumeCatcher() { - // Let the instance persist until exit. + // Let the instance persist until exit. } void VolumeCatcher::setVolume(F32 volume) { - pimpl->setVolume(volume); + pimpl->setVolume(volume); } void VolumeCatcher::setPan(F32 pan) { - pimpl->setPan(pan); + pimpl->setPan(pan); } void VolumeCatcher::pump() { - // No periodic tasks are necessary for this implementation. + // No periodic tasks are necessary for this implementation. } diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 60d91753d0..c1bba0fdd1 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -43,74 +43,74 @@ //////////////////////////////////////////////////////////////////////////////// // class MediaPluginCEF : - public MediaPluginBase + public MediaPluginBase { public: - MediaPluginCEF(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); - ~MediaPluginCEF(); + MediaPluginCEF(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginCEF(); - /*virtual*/ - void receiveMessage(const char* message_string); + /*virtual*/ + void receiveMessage(const char* message_string); private: - bool init(); - - void onPageChangedCallback(const unsigned char* pixels, int x, int y, const int width, const int height); - void onCustomSchemeURLCallback(std::string url, bool user_gesture, bool is_redirect); - void onConsoleMessageCallback(std::string message, std::string source, int line); - void onStatusMessageCallback(std::string value); - void onTitleChangeCallback(std::string title); - void onTooltipCallback(std::string text); - void onLoadStartCallback(); - void onRequestExitCallback(); - void onLoadEndCallback(int httpStatusCode, std::string url); - void onLoadError(int status, const std::string error_text); - void onAddressChangeCallback(std::string url); - void onOpenPopupCallback(std::string url, std::string target); - bool onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password); - void onCursorChangedCallback(dullahan::ECursorType type); - const std::vector<std::string> onFileDialog(dullahan::EFileDialogType dialog_type, const std::string dialog_title, const std::string default_file, const std::string dialog_accept_filter, bool& use_default); - bool onJSDialogCallback(const std::string origin_url, const std::string message_text, const std::string default_prompt_text); - bool onJSBeforeUnloadCallback(); - - void postDebugMessage(const std::string& msg); - void authResponse(LLPluginMessage &message); - - void keyEvent(dullahan::EKeyEvent key_event, LLSD native_key_data); - void unicodeInput(std::string event, LLSD native_key_data); - - void checkEditState(); + bool init(); + + void onPageChangedCallback(const unsigned char* pixels, int x, int y, const int width, const int height); + void onCustomSchemeURLCallback(std::string url, bool user_gesture, bool is_redirect); + void onConsoleMessageCallback(std::string message, std::string source, int line); + void onStatusMessageCallback(std::string value); + void onTitleChangeCallback(std::string title); + void onTooltipCallback(std::string text); + void onLoadStartCallback(); + void onRequestExitCallback(); + void onLoadEndCallback(int httpStatusCode, std::string url); + void onLoadError(int status, const std::string error_text); + void onAddressChangeCallback(std::string url); + void onOpenPopupCallback(std::string url, std::string target); + bool onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password); + void onCursorChangedCallback(dullahan::ECursorType type); + const std::vector<std::string> onFileDialog(dullahan::EFileDialogType dialog_type, const std::string dialog_title, const std::string default_file, const std::string dialog_accept_filter, bool& use_default); + bool onJSDialogCallback(const std::string origin_url, const std::string message_text, const std::string default_prompt_text); + bool onJSBeforeUnloadCallback(); + + void postDebugMessage(const std::string& msg); + void authResponse(LLPluginMessage &message); + + void keyEvent(dullahan::EKeyEvent key_event, LLSD native_key_data); + void unicodeInput(std::string event, LLSD native_key_data); + + void checkEditState(); void setVolume(); - bool mEnableMediaPluginDebugging; - std::string mHostLanguage; - bool mCookiesEnabled; - bool mPluginsEnabled; - bool mJavascriptEnabled; + bool mEnableMediaPluginDebugging; + std::string mHostLanguage; + bool mCookiesEnabled; + bool mPluginsEnabled; + bool mJavascriptEnabled; bool mProxyEnabled; std::string mProxyHost; int mProxyPort; - bool mDisableGPU; - bool mDisableNetworkService; - bool mUseMockKeyChain; - bool mDisableWebSecurity; - bool mFileAccessFromFileUrls; - std::string mUserAgentSubtring; - std::string mAuthUsername; - std::string mAuthPassword; - bool mAuthOK; - bool mCanCut; - bool mCanCopy; - bool mCanPaste; + bool mDisableGPU; + bool mDisableNetworkService; + bool mUseMockKeyChain; + bool mDisableWebSecurity; + bool mFileAccessFromFileUrls; + std::string mUserAgentSubtring; + std::string mAuthUsername; + std::string mAuthPassword; + bool mAuthOK; + bool mCanCut; + bool mCanCopy; + bool mCanPaste; std::string mRootCachePath; - std::string mCachePath; - std::string mContextCachePath; - std::string mCefLogFile; - bool mCefLogVerbose; - std::vector<std::string> mPickedFiles; - VolumeCatcher mVolumeCatcher; - F32 mCurVolume; - dullahan* mCEFLib; + std::string mCachePath; + std::string mContextCachePath; + std::string mCefLogFile; + bool mCefLogVerbose; + std::vector<std::string> mPickedFiles; + VolumeCatcher mVolumeCatcher; + F32 mCurVolume; + dullahan* mCEFLib; }; //////////////////////////////////////////////////////////////////////////////// @@ -118,109 +118,109 @@ private: MediaPluginCEF::MediaPluginCEF(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) : MediaPluginBase(host_send_func, host_user_data) { - mWidth = 0; - mHeight = 0; - mDepth = 4; - mPixels = 0; - mEnableMediaPluginDebugging = true; - mHostLanguage = "en"; - mCookiesEnabled = true; - mPluginsEnabled = false; - mJavascriptEnabled = true; + mWidth = 0; + mHeight = 0; + mDepth = 4; + mPixels = 0; + mEnableMediaPluginDebugging = true; + mHostLanguage = "en"; + mCookiesEnabled = true; + mPluginsEnabled = false; + mJavascriptEnabled = true; mProxyEnabled = false; mProxyHost = ""; mProxyPort = 0; - mDisableGPU = false; - mDisableNetworkService = true; - mUseMockKeyChain = true; - mDisableWebSecurity = false; - mFileAccessFromFileUrls = false; - mUserAgentSubtring = ""; - mAuthUsername = ""; - mAuthPassword = ""; - mAuthOK = false; - mCanCut = false; - mCanCopy = false; - mCanPaste = false; - mCachePath = ""; - mCefLogFile = ""; - mCefLogVerbose = false; - mPickedFiles.clear(); - mCurVolume = 0.0; - - mCEFLib = new dullahan(); - - setVolume(); + mDisableGPU = false; + mDisableNetworkService = true; + mUseMockKeyChain = true; + mDisableWebSecurity = false; + mFileAccessFromFileUrls = false; + mUserAgentSubtring = ""; + mAuthUsername = ""; + mAuthPassword = ""; + mAuthOK = false; + mCanCut = false; + mCanCopy = false; + mCanPaste = false; + mCachePath = ""; + mCefLogFile = ""; + mCefLogVerbose = false; + mPickedFiles.clear(); + mCurVolume = 0.0; + + mCEFLib = new dullahan(); + + setVolume(); } //////////////////////////////////////////////////////////////////////////////// // MediaPluginCEF::~MediaPluginCEF() { - mCEFLib->shutdown(); + mCEFLib->shutdown(); } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::postDebugMessage(const std::string& msg) { - if (mEnableMediaPluginDebugging) - { - std::stringstream str; - str << "@Media Msg> " << msg; - - LLPluginMessage debug_message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "debug_message"); - debug_message.setValue("message_text", str.str()); - debug_message.setValue("message_level", "info"); - sendMessage(debug_message); - } + if (mEnableMediaPluginDebugging) + { + std::stringstream str; + str << "@Media Msg> " << msg; + + LLPluginMessage debug_message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "debug_message"); + debug_message.setValue("message_text", str.str()); + debug_message.setValue("message_level", "info"); + sendMessage(debug_message); + } } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::onPageChangedCallback(const unsigned char* pixels, int x, int y, const int width, const int height) { - if( mPixels && pixels ) - { - if (mWidth == width && mHeight == height) - { - memcpy(mPixels, pixels, mWidth * mHeight * mDepth); - } - else - { - mCEFLib->setSize(mWidth, mHeight); - } - setDirty(0, 0, mWidth, mHeight); - } + if( mPixels && pixels ) + { + if (mWidth == width && mHeight == height) + { + memcpy(mPixels, pixels, mWidth * mHeight * mDepth); + } + else + { + mCEFLib->setSize(mWidth, mHeight); + } + setDirty(0, 0, mWidth, mHeight); + } } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::onConsoleMessageCallback(std::string message, std::string source, int line) { - std::stringstream str; - str << "Console message: " << message << " in file(" << source << ") at line " << line; - postDebugMessage(str.str()); + std::stringstream str; + str << "Console message: " << message << " in file(" << source << ") at line " << line; + postDebugMessage(str.str()); } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::onStatusMessageCallback(std::string value) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "status_text"); - message.setValue("status", value); - sendMessage(message); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "status_text"); + message.setValue("status", value); + sendMessage(message); } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::onTitleChangeCallback(std::string title) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); - message.setValue("name", title); - message.setValueBoolean("history_back_available", mCEFLib->canGoBack()); - message.setValueBoolean("history_forward_available", mCEFLib->canGoForward()); - sendMessage(message); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", title); + message.setValueBoolean("history_back_available", mCEFLib->canGoBack()); + message.setValueBoolean("history_forward_available", mCEFLib->canGoForward()); + sendMessage(message); } void MediaPluginCEF::onTooltipCallback(std::string text) @@ -233,183 +233,183 @@ void MediaPluginCEF::onTooltipCallback(std::string text) // void MediaPluginCEF::onLoadStartCallback() { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); - //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? - message.setValueBoolean("history_back_available", mCEFLib->canGoBack()); - message.setValueBoolean("history_forward_available", mCEFLib->canGoForward()); - sendMessage(message); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); + //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? + message.setValueBoolean("history_back_available", mCEFLib->canGoBack()); + message.setValueBoolean("history_forward_available", mCEFLib->canGoForward()); + sendMessage(message); } ///////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::onLoadError(int status, const std::string error_text) { - std::stringstream msg; + std::stringstream msg; - msg << "<b>Loading error!</b>"; - msg << "<p>"; - msg << "Message: " << error_text; - msg << "<br>"; - msg << "Code: " << status; + msg << "<b>Loading error!</b>"; + msg << "<p>"; + msg << "Message: " << error_text; + msg << "<br>"; + msg << "Code: " << status; - mCEFLib->showBrowserMessage(msg.str()); + mCEFLib->showBrowserMessage(msg.str()); } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::onRequestExitCallback() { - LLPluginMessage message("base", "goodbye"); - sendMessage(message); + LLPluginMessage message("base", "goodbye"); + sendMessage(message); - // Will trigger delete on next staticReceiveMessage() - mDeleteMe = true; + // Will trigger delete on next staticReceiveMessage() + mDeleteMe = true; } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::onLoadEndCallback(int httpStatusCode, std::string url) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); - //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? - message.setValueS32("result_code", httpStatusCode); - message.setValueBoolean("history_back_available", mCEFLib->canGoBack()); - message.setValueBoolean("history_forward_available", mCEFLib->canGoForward()); - message.setValue("uri", url); - sendMessage(message); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); + //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? + message.setValueS32("result_code", httpStatusCode); + message.setValueBoolean("history_back_available", mCEFLib->canGoBack()); + message.setValueBoolean("history_forward_available", mCEFLib->canGoForward()); + message.setValue("uri", url); + sendMessage(message); } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::onAddressChangeCallback(std::string url) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); - message.setValue("uri", url); - sendMessage(message); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); + message.setValue("uri", url); + sendMessage(message); } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::onOpenPopupCallback(std::string url, std::string target) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href"); - message.setValue("uri", url); - message.setValue("target", target); - sendMessage(message); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href"); + message.setValue("uri", url); + message.setValue("target", target); + sendMessage(message); } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::onCustomSchemeURLCallback(std::string url, bool user_gesture, bool is_redirect) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow"); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow"); message.setValue("uri", url); - // indicate if this interaction was from a user click (okay on a SLAPP) or + // indicate if this interaction was from a user click (okay on a SLAPP) or // via a navigation (e.g. a data URL - see SL-18151) (not okay on a SLAPP) const std::string nav_type = user_gesture ? "clicked" : "navigated"; - message.setValue("nav_type", nav_type); + message.setValue("nav_type", nav_type); message.setValueBoolean("is_redirect", is_redirect); - sendMessage(message); + sendMessage(message); } //////////////////////////////////////////////////////////////////////////////// // bool MediaPluginCEF::onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password) { - mAuthOK = false; + mAuthOK = false; - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_request"); - message.setValue("url", host); - message.setValue("realm", realm); - message.setValueBoolean("blocking_request", true); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_request"); + message.setValue("url", host); + message.setValue("realm", realm); + message.setValueBoolean("blocking_request", true); - // The "blocking_request" key in the message means this sendMessage call will block until a response is received. - sendMessage(message); + // The "blocking_request" key in the message means this sendMessage call will block until a response is received. + sendMessage(message); - if (mAuthOK) - { - username = mAuthUsername; - password = mAuthPassword; - } + if (mAuthOK) + { + username = mAuthUsername; + password = mAuthPassword; + } - return mAuthOK; + return mAuthOK; } //////////////////////////////////////////////////////////////////////////////// // const std::vector<std::string> MediaPluginCEF::onFileDialog(dullahan::EFileDialogType dialog_type, const std::string dialog_title, const std::string default_file, std::string dialog_accept_filter, bool& use_default) { - // do not use the default CEF file picker - use_default = false; + // do not use the default CEF file picker + use_default = false; - if (dialog_type == dullahan::FD_OPEN_FILE) - { - mPickedFiles.clear(); + if (dialog_type == dullahan::FD_OPEN_FILE) + { + mPickedFiles.clear(); - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file"); - message.setValueBoolean("blocking_request", true); - message.setValueBoolean("multiple_files", false); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file"); + message.setValueBoolean("blocking_request", true); + message.setValueBoolean("multiple_files", false); - sendMessage(message); + sendMessage(message); - return mPickedFiles; - } - else if (dialog_type == dullahan::FD_OPEN_MULTIPLE_FILES) - { - mPickedFiles.clear(); + return mPickedFiles; + } + else if (dialog_type == dullahan::FD_OPEN_MULTIPLE_FILES) + { + mPickedFiles.clear(); - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file"); - message.setValueBoolean("blocking_request", true); - message.setValueBoolean("multiple_files", true); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file"); + message.setValueBoolean("blocking_request", true); + message.setValueBoolean("multiple_files", true); - sendMessage(message); + sendMessage(message); - return mPickedFiles; - } - else if (dialog_type == dullahan::FD_SAVE_FILE) - { - mPickedFiles.clear(); - mAuthOK = false; + return mPickedFiles; + } + else if (dialog_type == dullahan::FD_SAVE_FILE) + { + mPickedFiles.clear(); + mAuthOK = false; - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "file_download"); - message.setValueBoolean("blocking_request", true); - message.setValue("filename", default_file); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "file_download"); + message.setValueBoolean("blocking_request", true); + message.setValue("filename", default_file); - sendMessage(message); + sendMessage(message); - return mPickedFiles; - } + return mPickedFiles; + } - return std::vector<std::string>(); + return std::vector<std::string>(); } //////////////////////////////////////////////////////////////////////////////// // bool MediaPluginCEF::onJSDialogCallback(const std::string origin_url, const std::string message_text, const std::string default_prompt_text) { - // return true indicates we suppress the JavaScript alert UI entirely - return true; + // return true indicates we suppress the JavaScript alert UI entirely + return true; } //////////////////////////////////////////////////////////////////////////////// // bool MediaPluginCEF::onJSBeforeUnloadCallback() { - // return true indicates we suppress the JavaScript UI entirely - return true; + // return true indicates we suppress the JavaScript UI entirely + return true; } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::onCursorChangedCallback(dullahan::ECursorType type) { - std::string name = ""; + std::string name = ""; - switch (type) - { + switch (type) + { case dullahan::CT_POINTER: name = "UI_CURSOR_ARROW"; break; @@ -419,9 +419,9 @@ void MediaPluginCEF::onCursorChangedCallback(dullahan::ECursorType type) case dullahan::CT_HAND: name = "UI_CURSOR_HAND"; break; - case dullahan::CT_IBEAM: - name = "UI_CURSOR_IBEAM"; - break; + case dullahan::CT_IBEAM: + name = "UI_CURSOR_IBEAM"; + break; case dullahan::CT_WAIT: name = "UI_CURSOR_WAIT"; break; @@ -491,111 +491,111 @@ void MediaPluginCEF::onCursorChangedCallback(dullahan::ECursorType type) //case dullahan::CT_GRABING: //case dullahan::CT_CUSTOM: - default: - LL_WARNS() << "Unknown cursor ID: " << (int)type << LL_ENDL; - break; - } + default: + LL_WARNS() << "Unknown cursor ID: " << (int)type << LL_ENDL; + break; + } - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "cursor_changed"); - message.setValue("name", name); - sendMessage(message); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "cursor_changed"); + message.setValue("name", name); + sendMessage(message); } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::authResponse(LLPluginMessage &message) { - mAuthOK = message.getValueBoolean("ok"); - if (mAuthOK) - { - mAuthUsername = message.getValue("username"); - mAuthPassword = message.getValue("password"); - } + mAuthOK = message.getValueBoolean("ok"); + if (mAuthOK) + { + mAuthUsername = message.getValue("username"); + mAuthPassword = message.getValue("password"); + } } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::receiveMessage(const char* message_string) { - // std::cerr << "MediaPluginCEF::receiveMessage: received message: \"" << message_string << "\"" << std::endl; - LLPluginMessage message_in; - - if (message_in.parse(message_string) >= 0) - { - std::string message_class = message_in.getClass(); - std::string message_name = message_in.getName(); - if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE) - { - if (message_name == "init") - { - LLPluginMessage message("base", "init_response"); - LLSD versions = LLSD::emptyMap(); - versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; - message.setValueLLSD("versions", versions); - - std::string plugin_version = "CEF plugin 1.1.412"; - message.setValue("plugin_version", plugin_version); - sendMessage(message); - } - else if (message_name == "idle") - { - mCEFLib->update(); - - mVolumeCatcher.pump(); - - // this seems bad but unless the state changes (it won't until we figure out - // how to get CEF to tell us if copy/cut/paste is available) then this function - // will return immediately - checkEditState(); - } - else if (message_name == "cleanup") - { - mCEFLib->requestExit(); - } - else if (message_name == "force_exit") - { - mDeleteMe = true; - } - else if (message_name == "shm_added") - { - SharedSegmentInfo info; - info.mAddress = message_in.getValuePointer("address"); - info.mSize = (size_t)message_in.getValueS32("size"); - std::string name = message_in.getValue("name"); - - mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - - } - else if (message_name == "shm_remove") - { - std::string name = message_in.getValue("name"); - - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if (iter != mSharedSegments.end()) - { - if (mPixels == iter->second.mAddress) - { - mPixels = NULL; - mTextureSegmentName.clear(); - } - mSharedSegments.erase(iter); - } - else - { - } - - LLPluginMessage message("base", "shm_remove_response"); - message.setValue("name", name); - sendMessage(message); - } - else - { - } - } - else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) - { + // std::cerr << "MediaPluginCEF::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + LLPluginMessage message_in; + + if (message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if (message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; + message.setValueLLSD("versions", versions); + + std::string plugin_version = "CEF plugin 1.1.412"; + message.setValue("plugin_version", plugin_version); + sendMessage(message); + } + else if (message_name == "idle") + { + mCEFLib->update(); + + mVolumeCatcher.pump(); + + // this seems bad but unless the state changes (it won't until we figure out + // how to get CEF to tell us if copy/cut/paste is available) then this function + // will return immediately + checkEditState(); + } + else if (message_name == "cleanup") + { + mCEFLib->requestExit(); + } + else if (message_name == "force_exit") + { + mDeleteMe = true; + } + else if (message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if (message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if (iter != mSharedSegments.end()) + { + if (mPixels == iter->second.mAddress) + { + mPixels = NULL; + mTextureSegmentName.clear(); + } + mSharedSegments.erase(iter); + } + else + { + } + + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { + } + } + else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { if (message_name == "init") { // event callbacks from Dullahan @@ -619,10 +619,10 @@ void MediaPluginCEF::receiveMessage(const char* message_string) dullahan::dullahan_settings settings; #if LL_WINDOWS - // As of CEF version 83+, for Windows versions, we need to tell CEF + // As of CEF version 83+, for Windows versions, we need to tell CEF // where the host helper process is since this DLL is not in the same - // dir as the executable that loaded it (SLPlugin.exe). The code in - // Dullahan that tried to figure out the location automatically uses + // dir as the executable that loaded it (SLPlugin.exe). The code in + // Dullahan that tried to figure out the location automatically uses // the location of the exe which isn't helpful so we tell it explicitly. std::vector<wchar_t> buffer(MAX_PATH + 1); GetCurrentDirectoryW(MAX_PATH, &buffer[0]); @@ -633,7 +633,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) // SL-15560: Product team overruled my change to set the default // embedded background color to match the floater background // and set it to white - settings.background_color = 0xffffffff; // white + settings.background_color = 0xffffffff; // white settings.cache_enabled = true; settings.root_cache_path = mRootCachePath; @@ -648,88 +648,88 @@ void MediaPluginCEF::receiveMessage(const char* message_string) proxy_url << mProxyHost << ":" << mProxyPort; settings.proxy_host_port = proxy_url.str(); } - settings.disable_gpu = mDisableGPU; + settings.disable_gpu = mDisableGPU; #if LL_DARWIN - settings.disable_network_service = mDisableNetworkService; - settings.use_mock_keychain = mUseMockKeyChain; + settings.disable_network_service = mDisableNetworkService; + settings.use_mock_keychain = mUseMockKeyChain; #endif // these were added to facilitate loading images directly into a local - // web page for the prototype 360 project in 2017 - something that is + // web page for the prototype 360 project in 2017 - something that is // disallowed normally by the browser security model. Now the the source // (cubemap) images are stores as JavaScript, we can avoid opening up - // this security hole (it was only set for the 360 floater but still - // a concern). Leaving them here, explicitly turn off vs removing - // entirely from this source file so that others are aware of them + // this security hole (it was only set for the 360 floater but still + // a concern). Leaving them here, explicitly turn off vs removing + // entirely from this source file so that others are aware of them // in the future. settings.disable_web_security = false; settings.file_access_from_file_urls = false; settings.flash_enabled = mPluginsEnabled; - // This setting applies to all plugins, not just Flash - // Regarding, SL-15559 PDF files do not load in CEF v91, - // it turns out that on Windows, PDF support is treated - // as a plugin on Windows only so turning all plugins - // off, disabled built in PDF support. (Works okay in - // macOS surprisingly). To mitigrate this, we set the global - // media enabled flag to whatever the consumer wants and - // explicitly disable Flash with a different setting (below) - settings.plugins_enabled = mPluginsEnabled; - - // SL-14897 Disable Flash support in the embedded browser - settings.flash_enabled = false; - - settings.flip_mouse_y = false; - settings.flip_pixels_y = true; - settings.frame_rate = 60; - settings.force_wave_audio = true; - settings.initial_height = 1024; - settings.initial_width = 1024; - settings.java_enabled = false; - settings.javascript_enabled = mJavascriptEnabled; - settings.media_stream_enabled = false; // MAINT-6060 - WebRTC media removed until we can add granularity/query UI - - settings.user_agent_substring = mCEFLib->makeCompatibleUserAgentString(mUserAgentSubtring); - settings.webgl_enabled = true; - settings.log_file = mCefLogFile; - settings.log_verbose = mCefLogVerbose; - settings.autoplay_without_gesture = true; - - std::vector<std::string> custom_schemes(1, "secondlife"); - mCEFLib->setCustomSchemes(custom_schemes); - - bool result = mCEFLib->init(settings); + // This setting applies to all plugins, not just Flash + // Regarding, SL-15559 PDF files do not load in CEF v91, + // it turns out that on Windows, PDF support is treated + // as a plugin on Windows only so turning all plugins + // off, disabled built in PDF support. (Works okay in + // macOS surprisingly). To mitigrate this, we set the global + // media enabled flag to whatever the consumer wants and + // explicitly disable Flash with a different setting (below) + settings.plugins_enabled = mPluginsEnabled; + + // SL-14897 Disable Flash support in the embedded browser + settings.flash_enabled = false; + + settings.flip_mouse_y = false; + settings.flip_pixels_y = true; + settings.frame_rate = 60; + settings.force_wave_audio = true; + settings.initial_height = 1024; + settings.initial_width = 1024; + settings.java_enabled = false; + settings.javascript_enabled = mJavascriptEnabled; + settings.media_stream_enabled = false; // MAINT-6060 - WebRTC media removed until we can add granularity/query UI + + settings.user_agent_substring = mCEFLib->makeCompatibleUserAgentString(mUserAgentSubtring); + settings.webgl_enabled = true; + settings.log_file = mCefLogFile; + settings.log_verbose = mCefLogVerbose; + settings.autoplay_without_gesture = true; + + std::vector<std::string> custom_schemes(1, "secondlife"); + mCEFLib->setCustomSchemes(custom_schemes); + + bool result = mCEFLib->init(settings); if (!result) { // if this fails, the media system in viewer will put up a message } - // now we can set page zoom factor - F32 factor = (F32)message_in.getValueReal("factor"); + // now we can set page zoom factor + F32 factor = (F32)message_in.getValueReal("factor"); #if LL_DARWIN - //temporary fix for SL-10473: issue with displaying checkboxes on Mojave - factor*=1.001; + //temporary fix for SL-10473: issue with displaying checkboxes on Mojave + factor*=1.001; #endif - mCEFLib->setPageZoom(factor); - - // Plugin gets to decide the texture parameters to use. - mDepth = 4; - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); - message.setValueS32("default_width", 1024); - message.setValueS32("default_height", 1024); - message.setValueS32("depth", mDepth); - message.setValueU32("internalformat", GL_RGB); - message.setValueU32("format", GL_BGRA); - message.setValueU32("type", GL_UNSIGNED_BYTE); - message.setValueBoolean("coords_opengl", true); - sendMessage(message); - } - else if (message_name == "set_user_data_path") - { - std::string user_data_path_cache = message_in.getValue("cache_path"); - std::string subfolder = message_in.getValue("username"); - - mRootCachePath = user_data_path_cache + "cef_cache"; + mCEFLib->setPageZoom(factor); + + // Plugin gets to decide the texture parameters to use. + mDepth = 4; + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + message.setValueS32("default_width", 1024); + message.setValueS32("default_height", 1024); + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGB); + message.setValueU32("format", GL_BGRA); + message.setValueU32("type", GL_UNSIGNED_BYTE); + message.setValueBoolean("coords_opengl", true); + sendMessage(message); + } + else if (message_name == "set_user_data_path") + { + std::string user_data_path_cache = message_in.getValue("cache_path"); + std::string subfolder = message_in.getValue("username"); + + mRootCachePath = user_data_path_cache + "cef_cache"; if (!subfolder.empty()) { std::string delim; @@ -746,132 +746,132 @@ void MediaPluginCEF::receiveMessage(const char* message_string) mCachePath = mRootCachePath; } mContextCachePath = ""; // disabled by "" - mCefLogFile = message_in.getValue("cef_log_file"); - mCefLogVerbose = message_in.getValueBoolean("cef_verbose_log"); - } - 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; - - mCEFLib->setSize(mWidth, mHeight); - }; - }; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); - message.setValue("name", name); - message.setValueS32("width", width); - message.setValueS32("height", height); - message.setValueS32("texture_width", texture_width); - message.setValueS32("texture_height", texture_height); - sendMessage(message); - - } - else if (message_name == "set_language_code") - { - mHostLanguage = message_in.getValue("language"); - } - else if (message_name == "load_uri") - { - std::string uri = message_in.getValue("uri"); - mCEFLib->navigate(uri); - } - else if (message_name == "execute_javascript") - { - std::string code = message_in.getValue("code"); - mCEFLib->executeJavaScript(code); - } - else if (message_name == "set_cookie") - { - std::string uri = message_in.getValue("uri"); - std::string name = message_in.getValue("name"); - std::string value = message_in.getValue("value"); - std::string domain = message_in.getValue("domain"); - std::string path = message_in.getValue("path"); - bool httponly = message_in.getValueBoolean("httponly"); - bool secure = message_in.getValueBoolean("secure"); - mCEFLib->setCookie(uri, name, value, domain, path, httponly, secure); - } - else if (message_name == "mouse_event") - { - std::string event = message_in.getValue("event"); - - S32 x = message_in.getValueS32("x"); - S32 y = message_in.getValueS32("y"); - - // only even send left mouse button events to the CEF library - // (partially prompted by crash in OS X CEF when sending right button events) - // we catch the right click in viewer and display our own context menu anyway - S32 button = message_in.getValueS32("button"); - dullahan::EMouseButton btn = dullahan::MB_MOUSE_BUTTON_LEFT; - - if (event == "down" && button == 0) - { - mCEFLib->mouseButton(btn, dullahan::ME_MOUSE_DOWN, x, y); - mCEFLib->setFocus(); - - std::stringstream str; - str << "Mouse down at = " << x << ", " << y; - postDebugMessage(str.str()); - } - else if (event == "up" && button == 0) - { - mCEFLib->mouseButton(btn, dullahan::ME_MOUSE_UP, x, y); - - std::stringstream str; - str << "Mouse up at = " << x << ", " << y; - postDebugMessage(str.str()); - } - else if (event == "double_click") - { - mCEFLib->mouseButton(btn, dullahan::ME_MOUSE_DOUBLE_CLICK, x, y); - } - else - { - mCEFLib->mouseMove(x, y); - } - } - else if (message_name == "scroll_event") - { - // Mouse coordinates for cef to be able to scroll 'containers' - S32 x = message_in.getValueS32("x"); - S32 y = message_in.getValueS32("y"); - - // Wheel's clicks - S32 delta_x = message_in.getValueS32("clicks_x"); - S32 delta_y = message_in.getValueS32("clicks_y"); - const int scaling_factor = 40; - delta_x *= -scaling_factor; - delta_y *= -scaling_factor; - - mCEFLib->mouseWheel(x, y, delta_x, delta_y); - } - else if (message_name == "text_event") - { - std::string event = message_in.getValue("event"); - LLSD native_key_data = message_in.getValueLLSD("native_key_data"); - unicodeInput(event, native_key_data); - } - else if (message_name == "key_event") - { + mCefLogFile = message_in.getValue("cef_log_file"); + mCefLogVerbose = message_in.getValueBoolean("cef_verbose_log"); + } + 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; + + mCEFLib->setSize(mWidth, mHeight); + }; + }; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + } + else if (message_name == "set_language_code") + { + mHostLanguage = message_in.getValue("language"); + } + else if (message_name == "load_uri") + { + std::string uri = message_in.getValue("uri"); + mCEFLib->navigate(uri); + } + else if (message_name == "execute_javascript") + { + std::string code = message_in.getValue("code"); + mCEFLib->executeJavaScript(code); + } + else if (message_name == "set_cookie") + { + std::string uri = message_in.getValue("uri"); + std::string name = message_in.getValue("name"); + std::string value = message_in.getValue("value"); + std::string domain = message_in.getValue("domain"); + std::string path = message_in.getValue("path"); + bool httponly = message_in.getValueBoolean("httponly"); + bool secure = message_in.getValueBoolean("secure"); + mCEFLib->setCookie(uri, name, value, domain, path, httponly, secure); + } + else if (message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + + S32 x = message_in.getValueS32("x"); + S32 y = message_in.getValueS32("y"); + + // only even send left mouse button events to the CEF library + // (partially prompted by crash in OS X CEF when sending right button events) + // we catch the right click in viewer and display our own context menu anyway + S32 button = message_in.getValueS32("button"); + dullahan::EMouseButton btn = dullahan::MB_MOUSE_BUTTON_LEFT; + + if (event == "down" && button == 0) + { + mCEFLib->mouseButton(btn, dullahan::ME_MOUSE_DOWN, x, y); + mCEFLib->setFocus(); + + std::stringstream str; + str << "Mouse down at = " << x << ", " << y; + postDebugMessage(str.str()); + } + else if (event == "up" && button == 0) + { + mCEFLib->mouseButton(btn, dullahan::ME_MOUSE_UP, x, y); + + std::stringstream str; + str << "Mouse up at = " << x << ", " << y; + postDebugMessage(str.str()); + } + else if (event == "double_click") + { + mCEFLib->mouseButton(btn, dullahan::ME_MOUSE_DOUBLE_CLICK, x, y); + } + else + { + mCEFLib->mouseMove(x, y); + } + } + else if (message_name == "scroll_event") + { + // Mouse coordinates for cef to be able to scroll 'containers' + S32 x = message_in.getValueS32("x"); + S32 y = message_in.getValueS32("y"); + + // Wheel's clicks + S32 delta_x = message_in.getValueS32("clicks_x"); + S32 delta_y = message_in.getValueS32("clicks_y"); + const int scaling_factor = 40; + delta_x *= -scaling_factor; + delta_y *= -scaling_factor; + + mCEFLib->mouseWheel(x, y, delta_x, delta_y); + } + else if (message_name == "text_event") + { + std::string event = message_in.getValue("event"); + LLSD native_key_data = message_in.getValueLLSD("native_key_data"); + unicodeInput(event, native_key_data); + } + else if (message_name == "key_event") + { #if LL_DARWIN - std::string event = message_in.getValue("event"); + std::string event = message_in.getValue("event"); LLSD native_key_data = message_in.getValueLLSD("native_key_data"); dullahan::EKeyEvent key_event = dullahan::KE_KEY_UP; @@ -887,139 +887,139 @@ void MediaPluginCEF::receiveMessage(const char* message_string) keyEvent(key_event, native_key_data); #else - std::string event = message_in.getValue("event"); - LLSD native_key_data = message_in.getValueLLSD("native_key_data"); - - // Treat unknown events as key-up for safety. - dullahan::EKeyEvent key_event = dullahan::KE_KEY_UP; - if (event == "down") - { - key_event = dullahan::KE_KEY_DOWN; - } - else if (event == "repeat") - { - key_event = dullahan::KE_KEY_REPEAT; - } - - keyEvent(key_event, native_key_data); + std::string event = message_in.getValue("event"); + LLSD native_key_data = message_in.getValueLLSD("native_key_data"); + + // Treat unknown events as key-up for safety. + dullahan::EKeyEvent key_event = dullahan::KE_KEY_UP; + if (event == "down") + { + key_event = dullahan::KE_KEY_DOWN; + } + else if (event == "repeat") + { + key_event = dullahan::KE_KEY_REPEAT; + } + + keyEvent(key_event, native_key_data); #endif - } - else if (message_name == "enable_media_plugin_debugging") - { - mEnableMediaPluginDebugging = message_in.getValueBoolean("enable"); - } - if (message_name == "pick_file_response") - { - LLSD file_list_llsd = message_in.getValueLLSD("file_list"); - - LLSD::array_const_iterator iter = file_list_llsd.beginArray(); - LLSD::array_const_iterator end = file_list_llsd.endArray(); - for (; iter != end; ++iter) - { - mPickedFiles.push_back(((*iter).asString())); - } - } - if (message_name == "auth_response") - { - authResponse(message_in); - } - if (message_name == "edit_cut") - { - mCEFLib->editCut(); - } - if (message_name == "edit_copy") - { - mCEFLib->editCopy(); - } - if (message_name == "edit_paste") - { - mCEFLib->editPaste(); - } - } - else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) - { - if (message_name == "set_page_zoom_factor") - { - F32 factor = (F32)message_in.getValueReal("factor"); + } + else if (message_name == "enable_media_plugin_debugging") + { + mEnableMediaPluginDebugging = message_in.getValueBoolean("enable"); + } + if (message_name == "pick_file_response") + { + LLSD file_list_llsd = message_in.getValueLLSD("file_list"); + + LLSD::array_const_iterator iter = file_list_llsd.beginArray(); + LLSD::array_const_iterator end = file_list_llsd.endArray(); + for (; iter != end; ++iter) + { + mPickedFiles.push_back(((*iter).asString())); + } + } + if (message_name == "auth_response") + { + authResponse(message_in); + } + if (message_name == "edit_cut") + { + mCEFLib->editCut(); + } + if (message_name == "edit_copy") + { + mCEFLib->editCopy(); + } + if (message_name == "edit_paste") + { + mCEFLib->editPaste(); + } + } + else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) + { + if (message_name == "set_page_zoom_factor") + { + F32 factor = (F32)message_in.getValueReal("factor"); #if LL_DARWIN - //temporary fix for SL-10473: issue with displaying checkboxes on Mojave - factor*=1.001; + //temporary fix for SL-10473: issue with displaying checkboxes on Mojave + factor*=1.001; #endif - mCEFLib->setPageZoom(factor); - } - if (message_name == "browse_stop") - { - mCEFLib->stop(); - } - else if (message_name == "browse_reload") - { - bool ignore_cache = true; - mCEFLib->reload(ignore_cache); - } - else if (message_name == "browse_forward") - { - mCEFLib->goForward(); - } - else if (message_name == "browse_back") - { - mCEFLib->goBack(); - } - else if (message_name == "cookies_enabled") - { - mCookiesEnabled = message_in.getValueBoolean("enable"); - } - else if (message_name == "clear_cookies") - { - mCEFLib->deleteAllCookies(); - } - else if (message_name == "set_user_agent") - { - mUserAgentSubtring = message_in.getValue("user_agent"); - } - else if (message_name == "show_web_inspector") - { - mCEFLib->showDevTools(); - } - else if (message_name == "plugins_enabled") - { - mPluginsEnabled = message_in.getValueBoolean("enable"); - } - else if (message_name == "javascript_enabled") - { - mJavascriptEnabled = message_in.getValueBoolean("enable"); - } - else if (message_name == "gpu_disabled") - { - mDisableGPU = message_in.getValueBoolean("disable"); - } + mCEFLib->setPageZoom(factor); + } + if (message_name == "browse_stop") + { + mCEFLib->stop(); + } + else if (message_name == "browse_reload") + { + bool ignore_cache = true; + mCEFLib->reload(ignore_cache); + } + else if (message_name == "browse_forward") + { + mCEFLib->goForward(); + } + else if (message_name == "browse_back") + { + mCEFLib->goBack(); + } + else if (message_name == "cookies_enabled") + { + mCookiesEnabled = message_in.getValueBoolean("enable"); + } + else if (message_name == "clear_cookies") + { + mCEFLib->deleteAllCookies(); + } + else if (message_name == "set_user_agent") + { + mUserAgentSubtring = message_in.getValue("user_agent"); + } + else if (message_name == "show_web_inspector") + { + mCEFLib->showDevTools(); + } + else if (message_name == "plugins_enabled") + { + mPluginsEnabled = message_in.getValueBoolean("enable"); + } + else if (message_name == "javascript_enabled") + { + mJavascriptEnabled = message_in.getValueBoolean("enable"); + } + else if (message_name == "gpu_disabled") + { + mDisableGPU = message_in.getValueBoolean("disable"); + } else if (message_name == "proxy_setup") { mProxyEnabled = message_in.getValueBoolean("enable"); mProxyHost = message_in.getValue("host"); mProxyPort = message_in.getValueS32("port"); } - else if (message_name == "web_security_disabled") - { - mDisableWebSecurity = message_in.getValueBoolean("disabled"); - } - else if (message_name == "file_access_from_file_urls") - { - mFileAccessFromFileUrls = message_in.getValueBoolean("enabled"); - } - } + else if (message_name == "web_security_disabled") + { + mDisableWebSecurity = message_in.getValueBoolean("disabled"); + } + else if (message_name == "file_access_from_file_urls") + { + mFileAccessFromFileUrls = message_in.getValueBoolean("enabled"); + } + } else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) { if (message_name == "set_volume") { - F32 volume = (F32)message_in.getValueReal("volume"); - mCurVolume = volume; + F32 volume = (F32)message_in.getValueReal("volume"); + mCurVolume = volume; setVolume(); } } else - { - }; - } + { + }; + } } //////////////////////////////////////////////////////////////////////////////// @@ -1027,49 +1027,49 @@ void MediaPluginCEF::receiveMessage(const char* message_string) void MediaPluginCEF::keyEvent(dullahan::EKeyEvent key_event, LLSD native_key_data = LLSD::emptyMap()) { #if LL_DARWIN - U32 event_modifiers = native_key_data["event_modifiers"].asInteger(); - U32 event_keycode = native_key_data["event_keycode"].asInteger(); - U32 event_chars = native_key_data["event_chars"].asInteger(); - U32 event_umodchars = native_key_data["event_umodchars"].asInteger(); - bool event_isrepeat = native_key_data["event_isrepeat"].asBoolean(); - - // adding new code below in unicodeInput means we don't send ascii chars - // here too or we get double key presses on a mac. - bool esc_key = (event_umodchars == 27); - bool tab_key_up = (event_umodchars == 9) && (key_event == dullahan::EKeyEvent::KE_KEY_UP); - if ((esc_key || ((unsigned char)event_chars < 0x10 || (unsigned char)event_chars >= 0x7f )) && !tab_key_up) - { - mCEFLib->nativeKeyboardEventOSX(key_event, event_modifiers, - event_keycode, event_chars, - event_umodchars, event_isrepeat); - } + U32 event_modifiers = native_key_data["event_modifiers"].asInteger(); + U32 event_keycode = native_key_data["event_keycode"].asInteger(); + U32 event_chars = native_key_data["event_chars"].asInteger(); + U32 event_umodchars = native_key_data["event_umodchars"].asInteger(); + bool event_isrepeat = native_key_data["event_isrepeat"].asBoolean(); + + // adding new code below in unicodeInput means we don't send ascii chars + // here too or we get double key presses on a mac. + bool esc_key = (event_umodchars == 27); + bool tab_key_up = (event_umodchars == 9) && (key_event == dullahan::EKeyEvent::KE_KEY_UP); + if ((esc_key || ((unsigned char)event_chars < 0x10 || (unsigned char)event_chars >= 0x7f )) && !tab_key_up) + { + mCEFLib->nativeKeyboardEventOSX(key_event, event_modifiers, + event_keycode, event_chars, + event_umodchars, event_isrepeat); + } #elif LL_WINDOWS - U32 msg = ll_U32_from_sd(native_key_data["msg"]); - U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); - U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); + U32 msg = ll_U32_from_sd(native_key_data["msg"]); + U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); + U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); - mCEFLib->nativeKeyboardEventWin(msg, wparam, lparam); + mCEFLib->nativeKeyboardEventWin(msg, wparam, lparam); #endif #if LL_LINUX - uint32_t native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); // this is actually the SDL event.key.keysym.sym; - uint32_t native_virtual_key_win = (uint32_t)(native_key_data["virtual_key_win"].asInteger()); - uint32_t native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); + uint32_t native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); // this is actually the SDL event.key.keysym.sym; + uint32_t native_virtual_key_win = (uint32_t)(native_key_data["virtual_key_win"].asInteger()); + uint32_t native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); - // only for non-printable keysyms, the actual text input is done in unicodeInput() below - if (native_virtual_key <= 0x1b || native_virtual_key >= 0x7f) - { - // set keypad flag, not sure if this even does anything - bool keypad = false; - if (native_virtual_key_win >= 0x60 && native_virtual_key_win <= 0x6f) - { - keypad = true; - } + // only for non-printable keysyms, the actual text input is done in unicodeInput() below + if (native_virtual_key <= 0x1b || native_virtual_key >= 0x7f) + { + // set keypad flag, not sure if this even does anything + bool keypad = false; + if (native_virtual_key_win >= 0x60 && native_virtual_key_win <= 0x6f) + { + keypad = true; + } - // yes, we send native_virtual_key_win twice because native_virtual_key breaks it - mCEFLib->nativeKeyboardEventSDL2(key_event, native_virtual_key, native_modifiers, keypad); - } + // yes, we send native_virtual_key_win twice because native_virtual_key breaks it + mCEFLib->nativeKeyboardEventSDL2(key_event, native_virtual_key, native_modifiers, keypad); + } #endif // LL_LINUX }; @@ -1077,14 +1077,14 @@ void MediaPluginCEF::keyEvent(dullahan::EKeyEvent key_event, LLSD native_key_dat void MediaPluginCEF::unicodeInput(std::string event, LLSD native_key_data = LLSD::emptyMap()) { #if LL_DARWIN - // i didn't think this code was needed for macOS but without it, the IME - // input in japanese (and likely others too) doesn't work correctly. - // see maint-7654 - U32 event_modifiers = native_key_data["event_modifiers"].asInteger(); - U32 event_keycode = native_key_data["event_keycode"].asInteger(); - U32 event_chars = native_key_data["event_chars"].asInteger(); - U32 event_umodchars = native_key_data["event_umodchars"].asInteger(); - bool event_isrepeat = native_key_data["event_isrepeat"].asBoolean(); + // i didn't think this code was needed for macOS but without it, the IME + // input in japanese (and likely others too) doesn't work correctly. + // see maint-7654 + U32 event_modifiers = native_key_data["event_modifiers"].asInteger(); + U32 event_keycode = native_key_data["event_keycode"].asInteger(); + U32 event_chars = native_key_data["event_chars"].asInteger(); + U32 event_umodchars = native_key_data["event_umodchars"].asInteger(); + bool event_isrepeat = native_key_data["event_isrepeat"].asBoolean(); dullahan::EKeyEvent key_event = dullahan::KE_KEY_UP; if (event == "down") @@ -1092,24 +1092,24 @@ void MediaPluginCEF::unicodeInput(std::string event, LLSD native_key_data = LLSD key_event = dullahan::KE_KEY_DOWN; } - mCEFLib->nativeKeyboardEventOSX(key_event, event_modifiers, - event_keycode, event_chars, - event_umodchars, event_isrepeat); + mCEFLib->nativeKeyboardEventOSX(key_event, event_modifiers, + event_keycode, event_chars, + event_umodchars, event_isrepeat); #elif LL_WINDOWS - event = ""; // not needed here but prevents unused var warning as error - U32 msg = ll_U32_from_sd(native_key_data["msg"]); - U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); - U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); - mCEFLib->nativeKeyboardEventWin(msg, wparam, lparam); + event = ""; // not needed here but prevents unused var warning as error + U32 msg = ll_U32_from_sd(native_key_data["msg"]); + U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); + U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); + mCEFLib->nativeKeyboardEventWin(msg, wparam, lparam); #endif #if LL_LINUX - uint32_t native_scan_code = (uint32_t)(native_key_data["sdl_sym"].asInteger()); - uint32_t native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); - uint32_t native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); + uint32_t native_scan_code = (uint32_t)(native_key_data["sdl_sym"].asInteger()); + uint32_t native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); + uint32_t native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); - mCEFLib->nativeKeyboardEvent(dullahan::KE_KEY_DOWN, native_scan_code, native_virtual_key, native_modifiers); + mCEFLib->nativeKeyboardEvent(dullahan::KE_KEY_DOWN, native_scan_code, native_virtual_key, native_modifiers); #endif // LL_LINUX }; @@ -1118,62 +1118,62 @@ void MediaPluginCEF::unicodeInput(std::string event, LLSD native_key_data = LLSD // void MediaPluginCEF::checkEditState() { - bool can_cut = mCEFLib->editCanCut(); - bool can_copy = mCEFLib->editCanCopy(); - bool can_paste = mCEFLib->editCanPaste(); - - if ((can_cut != mCanCut) || (can_copy != mCanCopy) || (can_paste != mCanPaste)) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_state"); - - if (can_cut != mCanCut) - { - mCanCut = can_cut; - message.setValueBoolean("cut", can_cut); - } - - if (can_copy != mCanCopy) - { - mCanCopy = can_copy; - message.setValueBoolean("copy", can_copy); - } - - if (can_paste != mCanPaste) - { - mCanPaste = can_paste; - message.setValueBoolean("paste", can_paste); - } - - sendMessage(message); - } + bool can_cut = mCEFLib->editCanCut(); + bool can_copy = mCEFLib->editCanCopy(); + bool can_paste = mCEFLib->editCanPaste(); + + if ((can_cut != mCanCut) || (can_copy != mCanCopy) || (can_paste != mCanPaste)) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_state"); + + if (can_cut != mCanCut) + { + mCanCut = can_cut; + message.setValueBoolean("cut", can_cut); + } + + if (can_copy != mCanCopy) + { + mCanCopy = can_copy; + message.setValueBoolean("copy", can_copy); + } + + if (can_paste != mCanPaste) + { + mCanPaste = can_paste; + message.setValueBoolean("paste", can_paste); + } + + sendMessage(message); + } } void MediaPluginCEF::setVolume() { - mVolumeCatcher.setVolume(mCurVolume); + mVolumeCatcher.setVolume(mCurVolume); } //////////////////////////////////////////////////////////////////////////////// // bool MediaPluginCEF::init() { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); - message.setValue("name", "CEF Plugin"); - sendMessage(message); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", "CEF Plugin"); + sendMessage(message); - return true; + return true; }; //////////////////////////////////////////////////////////////////////////////// // int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, - void* host_user_data, - LLPluginInstance::sendMessageFunction *plugin_send_func, - void **plugin_user_data) + void* host_user_data, + LLPluginInstance::sendMessageFunction *plugin_send_func, + void **plugin_user_data) { - MediaPluginCEF* self = new MediaPluginCEF(host_send_func, host_user_data); - *plugin_send_func = MediaPluginCEF::staticReceiveMessage; - *plugin_user_data = (void*)self; + MediaPluginCEF* self = new MediaPluginCEF(host_send_func, host_user_data); + *plugin_send_func = MediaPluginCEF::staticReceiveMessage; + *plugin_user_data = (void*)self; - return 0; + return 0; } diff --git a/indra/media_plugins/cef/volume_catcher.h b/indra/media_plugins/cef/volume_catcher.h index 337f2913d3..ea97a24947 100644 --- a/indra/media_plugins/cef/volume_catcher.h +++ b/indra/media_plugins/cef/volume_catcher.h @@ -1,4 +1,4 @@ -/** +/** * @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. * @@ -6,21 +6,21 @@ * $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 @@ -36,19 +36,19 @@ class VolumeCatcherImpl; class VolumeCatcher { public: - VolumeCatcher(); - ~VolumeCatcher(); + 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 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 - 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; + VolumeCatcherImpl *pimpl; }; #endif // VOLUME_CATCHER_H diff --git a/indra/media_plugins/cef/windows_volume_catcher.cpp b/indra/media_plugins/cef/windows_volume_catcher.cpp index 7a36123a11..e7daeb5f74 100644 --- a/indra/media_plugins/cef/windows_volume_catcher.cpp +++ b/indra/media_plugins/cef/windows_volume_catcher.cpp @@ -1,4 +1,4 @@ -/** +/** * @file windows_volume_catcher.cpp * @brief A Windows implementation of volume level control of all audio channels opened by a process. * @@ -6,21 +6,21 @@ * $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 @@ -32,24 +32,24 @@ #include <mmeapi.h> class VolumeCatcherImpl : public LLSingleton<VolumeCatcherImpl> { - LLSINGLETON(VolumeCatcherImpl); - // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. - ~VolumeCatcherImpl(); + LLSINGLETON(VolumeCatcherImpl); + // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. + ~VolumeCatcherImpl(); public: - void setVolume(F32 volume); - void setPan(F32 pan); - + void setVolume(F32 volume); + void setPan(F32 pan); + private: - F32 mVolume; - F32 mPan; - bool mSystemIsVistaOrHigher; + F32 mVolume; + F32 mPan; + bool mSystemIsVistaOrHigher; }; VolumeCatcherImpl::VolumeCatcherImpl() -: mVolume(1.0f), // default volume is max - mPan(0.f) // default pan is centered +: mVolume(1.0f), // default volume is max + mPan(0.f) // default pan is centered { } @@ -59,46 +59,46 @@ VolumeCatcherImpl::~VolumeCatcherImpl() void VolumeCatcherImpl::setVolume(F32 volume) { - mVolume = volume; - - // set both left/right to same volume - // TODO: use pan value to set independently - DWORD left_channel = (DWORD)(mVolume * 65535.0f); - DWORD right_channel = (DWORD)(mVolume * 65535.0f); - DWORD hw_volume = left_channel << 16 | right_channel; - ::waveOutSetVolume(NULL, hw_volume); + mVolume = volume; + + // set both left/right to same volume + // TODO: use pan value to set independently + DWORD left_channel = (DWORD)(mVolume * 65535.0f); + DWORD right_channel = (DWORD)(mVolume * 65535.0f); + DWORD hw_volume = left_channel << 16 | right_channel; + ::waveOutSetVolume(NULL, hw_volume); } void VolumeCatcherImpl::setPan(F32 pan) -{ // remember pan for calculating individual channel levels later - mPan = pan; +{ // remember pan for calculating individual channel levels later + mPan = pan; } ///////////////////////////////////////////////////// VolumeCatcher::VolumeCatcher() { - pimpl = VolumeCatcherImpl::getInstance(); + pimpl = VolumeCatcherImpl::getInstance(); } VolumeCatcher::~VolumeCatcher() { - // Let the instance persist until exit. + // Let the instance persist until exit. } void VolumeCatcher::setVolume(F32 volume) { - pimpl->setVolume(volume); + pimpl->setVolume(volume); } void VolumeCatcher::setPan(F32 pan) { - pimpl->setPan(pan); + pimpl->setPan(pan); } void VolumeCatcher::pump() { - // No periodic tasks are necessary for this implementation. + // No periodic tasks are necessary for this implementation. } diff --git a/indra/media_plugins/example/media_plugin_example.cpp b/indra/media_plugins/example/media_plugin_example.cpp index 650685fb94..0b22b7833f 100644 --- a/indra/media_plugins/example/media_plugin_example.cpp +++ b/indra/media_plugins/example/media_plugin_example.cpp @@ -39,30 +39,30 @@ //////////////////////////////////////////////////////////////////////////////// // class mediaPluginExample : - public MediaPluginBase + public MediaPluginBase { public: - mediaPluginExample(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); - ~mediaPluginExample(); + mediaPluginExample(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~mediaPluginExample(); - /*virtual*/ void receiveMessage(const char* message_string); + /*virtual*/ void receiveMessage(const char* message_string); private: - bool init(); - void update(F64 milliseconds); - bool mFirstTime; - - time_t mLastUpdateTime; - enum Constants { ENumObjects = 64 }; - unsigned char* mBackgroundPixels; - int mColorR[ENumObjects]; - int mColorG[ENumObjects]; - int mColorB[ENumObjects]; - int mXpos[ENumObjects]; - int mYpos[ENumObjects]; - int mXInc[ENumObjects]; - int mYInc[ENumObjects]; - int mBlockSize[ENumObjects]; + bool init(); + void update(F64 milliseconds); + bool mFirstTime; + + time_t mLastUpdateTime; + enum Constants { ENumObjects = 64 }; + unsigned char* mBackgroundPixels; + int mColorR[ENumObjects]; + int mColorG[ENumObjects]; + int mColorB[ENumObjects]; + int mXpos[ENumObjects]; + int mYpos[ENumObjects]; + int mXInc[ENumObjects]; + int mYInc[ENumObjects]; + int mBlockSize[ENumObjects]; }; //////////////////////////////////////////////////////////////////////////////// @@ -70,15 +70,15 @@ private: mediaPluginExample::mediaPluginExample(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) : MediaPluginBase(host_send_func, host_user_data) { - mFirstTime = true; - mTextureWidth = 0; - mTextureHeight = 0; - mWidth = 0; - mHeight = 0; - mDepth = 4; - mPixels = 0; - mLastUpdateTime = 0; - mBackgroundPixels = 0; + mFirstTime = true; + mTextureWidth = 0; + mTextureHeight = 0; + mWidth = 0; + mHeight = 0; + mDepth = 4; + mPixels = 0; + mLastUpdateTime = 0; + mBackgroundPixels = 0; } //////////////////////////////////////////////////////////////////////////////// @@ -91,305 +91,305 @@ 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 0.0.0"; - message.setValue("plugin_version", plugin_version); - sendMessage(message); - } - else if (message_name == "idle") - { - // no response is necessary here. - F64 time = message_in.getValueReal("time"); - - // Convert time to milliseconds for update() - update((int)(time * 1000.0f)); - } - else if (message_name == "cleanup") - { - LLPluginMessage message("base", "goodbye"); - sendMessage(message); - - mDeleteMe = true; - } - else if (message_name == "force_exit") - { - mDeleteMe = true; - } - else if (message_name == "shm_added") - { - SharedSegmentInfo info; - info.mAddress = message_in.getValuePointer("address"); - info.mSize = (size_t)message_in.getValueS32("size"); - std::string name = message_in.getValue("name"); - - mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - - } - else if (message_name == "shm_remove") - { - std::string name = message_in.getValue("name"); - - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if (iter != mSharedSegments.end()) - { - if (mPixels == iter->second.mAddress) - { - // This is the currently active pixel buffer. Make sure we stop drawing to it. - mPixels = NULL; - mTextureSegmentName.clear(); - } - mSharedSegments.erase(iter); - } - else - { - // std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; - } - - // Send the response so it can be cleaned up. - LLPluginMessage message("base", "shm_remove_response"); - message.setValue("name", name); - sendMessage(message); - } - else - { - // std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; - } - } - else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) - { - if (message_name == "init") - { - // Plugin gets to decide the texture parameters to use. - mDepth = 4; - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); - message.setValueS32("default_width", 1024); - message.setValueS32("default_height", 1024); - message.setValueS32("depth", mDepth); - message.setValueU32("internalformat", GL_RGB); - message.setValueU32("format", GL_RGBA); - message.setValueU32("type", GL_UNSIGNED_BYTE); - message.setValueBoolean("coords_opengl", true); - sendMessage(message); - } - else if (message_name == "size_change") - { - std::string name = message_in.getValue("name"); - S32 width = message_in.getValueS32("width"); - S32 height = message_in.getValueS32("height"); - S32 texture_width = message_in.getValueS32("texture_width"); - S32 texture_height = message_in.getValueS32("texture_height"); - - if (!name.empty()) - { - // Find the shared memory region with this name - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if (iter != mSharedSegments.end()) - { - mPixels = (unsigned char*)iter->second.mAddress; - mWidth = width; - mHeight = height; - - mTextureWidth = texture_width; - mTextureHeight = texture_height; - }; - }; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); - message.setValue("name", name); - message.setValueS32("width", width); - message.setValueS32("height", height); - message.setValueS32("texture_width", texture_width); - message.setValueS32("texture_height", texture_height); - sendMessage(message); - - mFirstTime = true; - mLastUpdateTime = 0; - - } - else if (message_name == "load_uri") - { - } - else if (message_name == "mouse_event") - { - std::string event = message_in.getValue("event"); - if (event == "down") - { - - } - else if (event == "up") - { - } - else if (event == "double_click") - { - } - } - } - else - { - }; - } + // std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + LLPluginMessage message_in; + + if (message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if (message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; + message.setValueLLSD("versions", versions); + + std::string plugin_version = "Example plugin 0.0.0"; + message.setValue("plugin_version", plugin_version); + sendMessage(message); + } + else if (message_name == "idle") + { + // no response is necessary here. + F64 time = message_in.getValueReal("time"); + + // Convert time to milliseconds for update() + update((int)(time * 1000.0f)); + } + else if (message_name == "cleanup") + { + LLPluginMessage message("base", "goodbye"); + sendMessage(message); + + mDeleteMe = true; + } + else if (message_name == "force_exit") + { + mDeleteMe = true; + } + else if (message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if (message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if (iter != mSharedSegments.end()) + { + if (mPixels == iter->second.mAddress) + { + // This is the currently active pixel buffer. Make sure we stop drawing to it. + mPixels = NULL; + mTextureSegmentName.clear(); + } + mSharedSegments.erase(iter); + } + else + { + // std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; + } + + // Send the response so it can be cleaned up. + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { + // std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if (message_name == "init") + { + // Plugin gets to decide the texture parameters to use. + mDepth = 4; + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + message.setValueS32("default_width", 1024); + message.setValueS32("default_height", 1024); + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGB); + message.setValueU32("format", GL_RGBA); + message.setValueU32("type", GL_UNSIGNED_BYTE); + message.setValueBoolean("coords_opengl", true); + sendMessage(message); + } + else if (message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + if (!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if (iter != mSharedSegments.end()) + { + mPixels = (unsigned char*)iter->second.mAddress; + mWidth = width; + mHeight = height; + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + }; + }; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + mFirstTime = true; + mLastUpdateTime = 0; + + } + else if (message_name == "load_uri") + { + } + else if (message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + if (event == "down") + { + + } + else if (event == "up") + { + } + else if (event == "double_click") + { + } + } + } + else + { + }; + } } //////////////////////////////////////////////////////////////////////////////// // void mediaPluginExample::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 (time(NULL) > mLastUpdateTime + 3) - { - const int num_squares = rand() % 20 + 4; - int sqr1_r = rand() % 0x80 + 0x20; - int sqr1_g = rand() % 0x80 + 0x20; - int sqr1_b = rand() % 0x80 + 0x20; - int sqr2_r = rand() % 0x80 + 0x20; - int sqr2_g = rand() % 0x80 + 0x20; - int sqr2_b = rand() % 0x80 + 0x20; - - for (int y1 = 0; y1 < num_squares; ++y1) - { - for (int x1 = 0; x1 < num_squares; ++x1) - { - int px_start = mWidth * x1 / num_squares; - int px_end = (mWidth * (x1 + 1)) / num_squares; - int py_start = mHeight * y1 / num_squares; - int py_end = (mHeight * (y1 + 1)) / num_squares; - - for (int y2 = py_start; y2 < py_end; ++y2) - { - for (int x2 = px_start; x2 < px_end; ++x2) - { - int rowspan = mWidth * mDepth; - - if ((y1 % 2) ^ (x1 % 2)) - { - mBackgroundPixels[y2 * rowspan + x2 * mDepth + 0] = sqr1_r; - mBackgroundPixels[y2 * rowspan + x2 * mDepth + 1] = sqr1_g; - mBackgroundPixels[y2 * rowspan + x2 * mDepth + 2] = sqr1_b; - } - else - { - mBackgroundPixels[y2 * rowspan + x2 * mDepth + 0] = sqr2_r; - mBackgroundPixels[y2 * rowspan + x2 * mDepth + 1] = sqr2_g; - mBackgroundPixels[y2 * rowspan + x2 * mDepth + 2] = sqr2_b; - }; - }; - }; - }; - }; - - time(&mLastUpdateTime); - }; - - memcpy(mPixels, mBackgroundPixels, mWidth * mHeight * mDepth); - - for (int n = 0; n < ENumObjects; ++n) - { - if (rand() % 50 == 0) - { - mXInc[n] = 0; - while (mXInc[n] == 0) - mXInc[n] = rand() % 7 - 3; - - mYInc[n] = 0; - while (mYInc[n] == 0) - mYInc[n] = rand() % 9 - 4; - }; - - if (mXpos[n] + mXInc[n] < 0 || mXpos[n] + mXInc[n] >= mWidth - mBlockSize[n]) - mXInc[n] = -mXInc[n]; - - if (mYpos[n] + mYInc[n] < 0 || mYpos[n] + mYInc[n] >= mHeight - mBlockSize[n]) - mYInc[n] = -mYInc[n]; - - mXpos[n] += mXInc[n]; - mYpos[n] += mYInc[n]; - - for (int y = 0; y < mBlockSize[n]; ++y) - { - for (int x = 0; x < mBlockSize[n]; ++x) - { - mPixels[(mXpos[n] + x) * mDepth + (mYpos[n] + y) * mDepth * mWidth + 0] = mColorR[n]; - mPixels[(mXpos[n] + x) * mDepth + (mYpos[n] + y) * mDepth * mWidth + 1] = mColorG[n]; - mPixels[(mXpos[n] + x) * mDepth + (mYpos[n] + y) * mDepth * mWidth + 2] = mColorB[n]; - }; - }; - }; - - setDirty(0, 0, mWidth, mHeight); + if (mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048) + return; + + if (mPixels == 0) + return; + + if (mFirstTime) + { + for (int n = 0; n < ENumObjects; ++n) + { + mXpos[n] = (mWidth / 2) + rand() % (mWidth / 16) - (mWidth / 32); + mYpos[n] = (mHeight / 2) + rand() % (mHeight / 16) - (mHeight / 32); + + mColorR[n] = rand() % 0x60 + 0x60; + mColorG[n] = rand() % 0x60 + 0x60; + mColorB[n] = rand() % 0x60 + 0x60; + + mXInc[n] = 0; + while (mXInc[n] == 0) + mXInc[n] = rand() % 7 - 3; + + mYInc[n] = 0; + while (mYInc[n] == 0) + mYInc[n] = rand() % 9 - 4; + + mBlockSize[n] = rand() % 0x30 + 0x10; + }; + + delete[] mBackgroundPixels; + + mBackgroundPixels = new unsigned char[mWidth * mHeight * mDepth]; + + mFirstTime = false; + }; + + if (time(NULL) > mLastUpdateTime + 3) + { + const int num_squares = rand() % 20 + 4; + int sqr1_r = rand() % 0x80 + 0x20; + int sqr1_g = rand() % 0x80 + 0x20; + int sqr1_b = rand() % 0x80 + 0x20; + int sqr2_r = rand() % 0x80 + 0x20; + int sqr2_g = rand() % 0x80 + 0x20; + int sqr2_b = rand() % 0x80 + 0x20; + + for (int y1 = 0; y1 < num_squares; ++y1) + { + for (int x1 = 0; x1 < num_squares; ++x1) + { + int px_start = mWidth * x1 / num_squares; + int px_end = (mWidth * (x1 + 1)) / num_squares; + int py_start = mHeight * y1 / num_squares; + int py_end = (mHeight * (y1 + 1)) / num_squares; + + for (int y2 = py_start; y2 < py_end; ++y2) + { + for (int x2 = px_start; x2 < px_end; ++x2) + { + int rowspan = mWidth * mDepth; + + if ((y1 % 2) ^ (x1 % 2)) + { + mBackgroundPixels[y2 * rowspan + x2 * mDepth + 0] = sqr1_r; + mBackgroundPixels[y2 * rowspan + x2 * mDepth + 1] = sqr1_g; + mBackgroundPixels[y2 * rowspan + x2 * mDepth + 2] = sqr1_b; + } + else + { + mBackgroundPixels[y2 * rowspan + x2 * mDepth + 0] = sqr2_r; + mBackgroundPixels[y2 * rowspan + x2 * mDepth + 1] = sqr2_g; + mBackgroundPixels[y2 * rowspan + x2 * mDepth + 2] = sqr2_b; + }; + }; + }; + }; + }; + + time(&mLastUpdateTime); + }; + + memcpy(mPixels, mBackgroundPixels, mWidth * mHeight * mDepth); + + for (int n = 0; n < ENumObjects; ++n) + { + if (rand() % 50 == 0) + { + mXInc[n] = 0; + while (mXInc[n] == 0) + mXInc[n] = rand() % 7 - 3; + + mYInc[n] = 0; + while (mYInc[n] == 0) + mYInc[n] = rand() % 9 - 4; + }; + + if (mXpos[n] + mXInc[n] < 0 || mXpos[n] + mXInc[n] >= mWidth - mBlockSize[n]) + mXInc[n] = -mXInc[n]; + + if (mYpos[n] + mYInc[n] < 0 || mYpos[n] + mYInc[n] >= mHeight - mBlockSize[n]) + mYInc[n] = -mYInc[n]; + + mXpos[n] += mXInc[n]; + mYpos[n] += mYInc[n]; + + for (int y = 0; y < mBlockSize[n]; ++y) + { + for (int x = 0; x < mBlockSize[n]; ++x) + { + mPixels[(mXpos[n] + x) * mDepth + (mYpos[n] + y) * mDepth * mWidth + 0] = mColorR[n]; + mPixels[(mXpos[n] + x) * mDepth + (mYpos[n] + y) * mDepth * mWidth + 1] = mColorG[n]; + mPixels[(mXpos[n] + x) * mDepth + (mYpos[n] + y) * mDepth * mWidth + 2] = mColorB[n]; + }; + }; + }; + + setDirty(0, 0, mWidth, mHeight); }; //////////////////////////////////////////////////////////////////////////////// // bool mediaPluginExample::init() { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); - message.setValue("name", "Example Plugin"); - sendMessage(message); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", "Example Plugin"); + sendMessage(message); - return true; + return true; }; //////////////////////////////////////////////////////////////////////////////// // int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, - void* host_user_data, - LLPluginInstance::sendMessageFunction *plugin_send_func, - void **plugin_user_data) + void* host_user_data, + LLPluginInstance::sendMessageFunction *plugin_send_func, + void **plugin_user_data) { - mediaPluginExample* self = new mediaPluginExample(host_send_func, host_user_data); - *plugin_send_func = mediaPluginExample::staticReceiveMessage; - *plugin_user_data = (void*)self; + mediaPluginExample* self = new mediaPluginExample(host_send_func, host_user_data); + *plugin_send_func = mediaPluginExample::staticReceiveMessage; + *plugin_user_data = (void*)self; - return 0; + return 0; } diff --git a/indra/media_plugins/gstreamer10/llmediaimplgstreamer.h b/indra/media_plugins/gstreamer10/llmediaimplgstreamer.h index 6bc272c009..cae11a5cb3 100644 --- a/indra/media_plugins/gstreamer10/llmediaimplgstreamer.h +++ b/indra/media_plugins/gstreamer10/llmediaimplgstreamer.h @@ -1,4 +1,4 @@ -/** +/** * @file llmediaimplgstreamer.h * @author Tofu Linden * @brief implementation that supports media playback via GStreamer. @@ -7,21 +7,21 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ * @endcond @@ -44,8 +44,8 @@ extern "C" { extern "C" { gboolean llmediaimplgstreamer_bus_callback (GstBus *bus, - GstMessage *message, - gpointer data); + GstMessage *message, + gpointer data); } #endif // LL_GSTREAMER010_ENABLED diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index 89144922cc..a5d8f885fd 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -50,53 +50,53 @@ typedef SSIZE_T ssize_t; //////////////////////////////////////////////////////////////////////////////// // class MediaPluginLibVLC : - public MediaPluginBase + public MediaPluginBase { public: - MediaPluginLibVLC(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); - ~MediaPluginLibVLC(); + MediaPluginLibVLC(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginLibVLC(); - /*virtual*/ void receiveMessage(const char* message_string); + /*virtual*/ void receiveMessage(const char* message_string); private: - bool init(); + bool init(); - void initVLC(); - void playMedia(); - void resetVLC(); - void setVolume(const F64 volume); - void setVolumeVLC(); - void updateTitle(const char* title); + void initVLC(); + void playMedia(); + void resetVLC(); + void setVolume(const F64 volume); + void setVolumeVLC(); + void updateTitle(const char* title); - static void* lock(void* data, void** p_pixels); - static void unlock(void* data, void* id, void* const* raw_pixels); - static void display(void* data, void* id); + static void* lock(void* data, void** p_pixels); + static void unlock(void* data, void* id, void* const* raw_pixels); + static void display(void* data, void* id); - /*virtual*/ void setDirty(int left, int top, int right, int bottom) /* override, but that is not supported in gcc 4.6 */; + /*virtual*/ void setDirty(int left, int top, int right, int bottom) /* override, but that is not supported in gcc 4.6 */; void setDurationDirty(); - static void eventCallbacks(const libvlc_event_t* event, void* ptr); + static void eventCallbacks(const libvlc_event_t* event, void* ptr); - libvlc_instance_t* mLibVLC; - libvlc_media_t* mLibVLCMedia; - libvlc_media_player_t* mLibVLCMediaPlayer; + libvlc_instance_t* mLibVLC; + libvlc_media_t* mLibVLCMedia; + libvlc_media_player_t* mLibVLCMediaPlayer; - struct mLibVLCContext - { - unsigned char* texture_pixels; - libvlc_media_player_t* mp; - MediaPluginLibVLC* parent; - }; - struct mLibVLCContext mLibVLCCallbackContext; + struct mLibVLCContext + { + unsigned char* texture_pixels; + libvlc_media_player_t* mp; + MediaPluginLibVLC* parent; + }; + struct mLibVLCContext mLibVLCCallbackContext; - std::string mURL; - F64 mCurVolume; + std::string mURL; + F64 mCurVolume; - bool mIsLooping; + bool mIsLooping; - F64 mCurTime; - F64 mDuration; - EStatus mVlcStatus; + F64 mCurTime; + F64 mDuration; + EStatus mVlcStatus; }; //////////////////////////////////////////////////////////////////////////////// @@ -104,28 +104,28 @@ private: MediaPluginLibVLC::MediaPluginLibVLC(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) : MediaPluginBase(host_send_func, host_user_data) { - mTextureWidth = 0; - mTextureHeight = 0; - mWidth = 0; - mHeight = 0; - mDepth = 4; - mPixels = 0; + mTextureWidth = 0; + mTextureHeight = 0; + mWidth = 0; + mHeight = 0; + mDepth = 4; + mPixels = 0; - mLibVLC = 0; - mLibVLCMedia = 0; - mLibVLCMediaPlayer = 0; + mLibVLC = 0; + mLibVLCMedia = 0; + mLibVLCMediaPlayer = 0; - mCurVolume = 0.0; + mCurVolume = 0.0; - mIsLooping = false; + mIsLooping = false; - mCurTime = 0.0; - mDuration = 0.0; + mCurTime = 0.0; + mDuration = 0.0; - mURL = std::string(); + mURL = std::string(); - mVlcStatus = STATUS_NONE; - setStatus(STATUS_NONE); + mVlcStatus = STATUS_NONE; + setStatus(STATUS_NONE); } //////////////////////////////////////////////////////////////////////////////// @@ -138,80 +138,80 @@ MediaPluginLibVLC::~MediaPluginLibVLC() // void* MediaPluginLibVLC::lock(void* data, void** p_pixels) { - struct mLibVLCContext* context = (mLibVLCContext*)data; + struct mLibVLCContext* context = (mLibVLCContext*)data; - *p_pixels = context->texture_pixels; + *p_pixels = context->texture_pixels; - return NULL; + return NULL; } ///////////////////////////////////////////////////////////////////////////////// // void MediaPluginLibVLC::unlock(void* data, void* id, void* const* raw_pixels) { - // nothing to do here for the moment - // we *could* modify pixels here to, for example, Y flip, but this is done with - // a VLC video filter transform. + // nothing to do here for the moment + // we *could* modify pixels here to, for example, Y flip, but this is done with + // a VLC video filter transform. } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginLibVLC::display(void* data, void* id) { - struct mLibVLCContext* context = (mLibVLCContext*)data; + struct mLibVLCContext* context = (mLibVLCContext*)data; - context->parent->setDirty(0, 0, context->parent->mWidth, context->parent->mHeight); + context->parent->setDirty(0, 0, context->parent->mWidth, context->parent->mHeight); } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginLibVLC::initVLC() { - char const* vlc_argv[] = - { - "--no-xlib", - "--video-filter=transform{type=vflip}", // MAINT-6578 Y flip textures in plugin vs client - }; + char const* vlc_argv[] = + { + "--no-xlib", + "--video-filter=transform{type=vflip}", // MAINT-6578 Y flip textures in plugin vs client + }; #if LL_DARWIN - setenv("VLC_PLUGIN_PATH", ".", 1); + setenv("VLC_PLUGIN_PATH", ".", 1); #endif - int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv); - mLibVLC = libvlc_new(vlc_argc, vlc_argv); + int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv); + mLibVLC = libvlc_new(vlc_argc, vlc_argv); - if (!mLibVLC) - { - // for the moment, if this fails, the plugin will fail and - // the media sub-system will tell the viewer something went wrong. - } + if (!mLibVLC) + { + // for the moment, if this fails, the plugin will fail and + // the media sub-system will tell the viewer something went wrong. + } } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginLibVLC::resetVLC() { - libvlc_media_player_stop(mLibVLCMediaPlayer); - libvlc_media_player_release(mLibVLCMediaPlayer); - libvlc_release(mLibVLC); + libvlc_media_player_stop(mLibVLCMediaPlayer); + libvlc_media_player_release(mLibVLCMediaPlayer); + libvlc_release(mLibVLC); } //////////////////////////////////////////////////////////////////////////////// // *virtual* void MediaPluginLibVLC::setDirty(int left, int top, int right, int bottom) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated"); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated"); - message.setValueS32("left", left); - message.setValueS32("top", top); - message.setValueS32("right", right); - message.setValueS32("bottom", bottom); + message.setValueS32("left", left); + message.setValueS32("top", top); + message.setValueS32("right", right); + message.setValueS32("bottom", bottom); - message.setValueReal("current_time", mCurTime); - message.setValueReal("duration", mDuration); - message.setValueReal("current_rate", 1.0f); + message.setValueReal("current_time", mCurTime); + message.setValueReal("duration", mDuration); + message.setValueReal("current_rate", 1.0f); - sendMessage(message); + sendMessage(message); } //////////////////////////////////////////////////////////////////////////////// @@ -231,363 +231,363 @@ void MediaPluginLibVLC::setDurationDirty() // void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr) { - MediaPluginLibVLC* parent = (MediaPluginLibVLC*)ptr; - if (parent == 0) - { - return; - } - - switch (event->type) - { - case libvlc_MediaPlayerOpening: - parent->mVlcStatus = STATUS_LOADING; - break; - - case libvlc_MediaPlayerPlaying: - parent->mDuration = (float)(libvlc_media_get_duration(parent->mLibVLCMedia)) / 1000.0f; - parent->mVlcStatus = STATUS_PLAYING; - parent->setVolumeVLC(); + MediaPluginLibVLC* parent = (MediaPluginLibVLC*)ptr; + if (parent == 0) + { + return; + } + + switch (event->type) + { + case libvlc_MediaPlayerOpening: + parent->mVlcStatus = STATUS_LOADING; + break; + + case libvlc_MediaPlayerPlaying: + parent->mDuration = (float)(libvlc_media_get_duration(parent->mLibVLCMedia)) / 1000.0f; + parent->mVlcStatus = STATUS_PLAYING; + parent->setVolumeVLC(); parent->setDurationDirty(); - break; + break; - case libvlc_MediaPlayerPaused: - parent->mVlcStatus = STATUS_PAUSED; - break; + case libvlc_MediaPlayerPaused: + parent->mVlcStatus = STATUS_PAUSED; + break; - case libvlc_MediaPlayerStopped: - parent->mVlcStatus = STATUS_DONE; - break; + case libvlc_MediaPlayerStopped: + parent->mVlcStatus = STATUS_DONE; + break; - case libvlc_MediaPlayerEndReached: - parent->mVlcStatus = STATUS_DONE; + case libvlc_MediaPlayerEndReached: + parent->mVlcStatus = STATUS_DONE; parent->mCurTime = parent->mDuration; parent->setDurationDirty(); - break; + break; - case libvlc_MediaPlayerEncounteredError: - parent->mVlcStatus = STATUS_ERROR; - break; + case libvlc_MediaPlayerEncounteredError: + parent->mVlcStatus = STATUS_ERROR; + break; - case libvlc_MediaPlayerTimeChanged: - parent->mCurTime = (float)libvlc_media_player_get_time(parent->mLibVLCMediaPlayer) / 1000.0f; + case libvlc_MediaPlayerTimeChanged: + parent->mCurTime = (float)libvlc_media_player_get_time(parent->mLibVLCMediaPlayer) / 1000.0f; if (parent->mVlcStatus == STATUS_DONE && libvlc_media_player_is_playing(parent->mLibVLCMediaPlayer)) { parent->mVlcStatus = STATUS_PLAYING; } parent->setDurationDirty(); - break; + break; - case libvlc_MediaPlayerPositionChanged: - break; + case libvlc_MediaPlayerPositionChanged: + break; - case libvlc_MediaPlayerLengthChanged: - parent->mDuration = (float)libvlc_media_get_duration(parent->mLibVLCMedia) / 1000.0f; + case libvlc_MediaPlayerLengthChanged: + parent->mDuration = (float)libvlc_media_get_duration(parent->mLibVLCMedia) / 1000.0f; parent->setDurationDirty(); - break; - - case libvlc_MediaPlayerTitleChanged: - { - char* title = libvlc_media_get_meta(parent->mLibVLCMedia, libvlc_meta_Title); - if (title) - { - parent->updateTitle(title); - } - } - break; - } + break; + + case libvlc_MediaPlayerTitleChanged: + { + char* title = libvlc_media_get_meta(parent->mLibVLCMedia, libvlc_meta_Title); + if (title) + { + parent->updateTitle(title); + } + } + break; + } } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginLibVLC::playMedia() { - if (mURL.length() == 0) - { - return; - } - - // A new call to play the media is received after the initial one. Typically - // this is due to a size change request either as the media naturally resizes - // to the size of the prim container, or else, as a 2D window is resized by the - // user. Stopping the media, helps avoid a race condition where the media pixel - // buffer size is out of sync with the declared size (width/height) for a frame - // or two and the plugin crashes as VLC tries to decode a frame into unallocated - // memory. - if (mLibVLCMediaPlayer) - { - libvlc_media_player_stop(mLibVLCMediaPlayer); - } - - mLibVLCMedia = libvlc_media_new_location(mLibVLC, mURL.c_str()); - if (!mLibVLCMedia) - { - mLibVLCMediaPlayer = 0; - setStatus(STATUS_ERROR); - return; - } - - mLibVLCMediaPlayer = libvlc_media_player_new_from_media(mLibVLCMedia); - if (!mLibVLCMediaPlayer) - { - setStatus(STATUS_ERROR); - return; - } - - // listen to events - libvlc_event_manager_t* em = libvlc_media_player_event_manager(mLibVLCMediaPlayer); - if (em) - { - libvlc_event_attach(em, libvlc_MediaPlayerOpening, eventCallbacks, this); - libvlc_event_attach(em, libvlc_MediaPlayerPlaying, eventCallbacks, this); - libvlc_event_attach(em, libvlc_MediaPlayerPaused, eventCallbacks, this); - libvlc_event_attach(em, libvlc_MediaPlayerStopped, eventCallbacks, this); - libvlc_event_attach(em, libvlc_MediaPlayerEndReached, eventCallbacks, this); - libvlc_event_attach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, this); - libvlc_event_attach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, this); - libvlc_event_attach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, this); - libvlc_event_attach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, this); - libvlc_event_attach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, this); - } - - libvlc_video_set_callbacks(mLibVLCMediaPlayer, lock, unlock, display, &mLibVLCCallbackContext); - libvlc_video_set_format(mLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth); - - mLibVLCCallbackContext.parent = this; - mLibVLCCallbackContext.texture_pixels = mPixels; - mLibVLCCallbackContext.mp = mLibVLCMediaPlayer; - - // Send a "navigate begin" event. - // This is really a browser message but the QuickTime plugin did it and - // the media system relies on this message to update internal state so we must send it too - // Note: see "navigate_complete" message below too - // https://jira.secondlife.com/browse/MAINT-6528 - LLPluginMessage message_begin(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); - message_begin.setValue("uri", mURL); - message_begin.setValueBoolean("history_back_available", false); - message_begin.setValueBoolean("history_forward_available", false); - sendMessage(message_begin); - - // volume level gets set before VLC is initialized (thanks media system) so we have to record - // it in mCurVolume and set it again here so that volume levels are correctly initialized - setVolume(mCurVolume); - - setStatus(STATUS_LOADED); - - // note this relies on the "set_loop" message arriving before the "start" (play) one - // but that appears to always be the case - if (mIsLooping) - { - libvlc_media_add_option(mLibVLCMedia, "input-repeat=65535"); - } - - libvlc_media_player_play(mLibVLCMediaPlayer); - - // send a "location_changed" message - this informs the media system - // that a new URL is the 'current' one and is used extensively. - // Again, this is really a browser message but we will use it here. - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); - message.setValue("uri", mURL); - sendMessage(message); - - // Send a "navigate complete" event. - // This is really a browser message but the QuickTime plugin did it and - // the media system relies on this message to update internal state so we must send it too - // Note: see "navigate_begin" message above too - // https://jira.secondlife.com/browse/MAINT-6528 - LLPluginMessage message_complete(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); - message_complete.setValue("uri", mURL); - message_complete.setValueS32("result_code", 200); - message_complete.setValue("result_string", "OK"); - sendMessage(message_complete); + if (mURL.length() == 0) + { + return; + } + + // A new call to play the media is received after the initial one. Typically + // this is due to a size change request either as the media naturally resizes + // to the size of the prim container, or else, as a 2D window is resized by the + // user. Stopping the media, helps avoid a race condition where the media pixel + // buffer size is out of sync with the declared size (width/height) for a frame + // or two and the plugin crashes as VLC tries to decode a frame into unallocated + // memory. + if (mLibVLCMediaPlayer) + { + libvlc_media_player_stop(mLibVLCMediaPlayer); + } + + mLibVLCMedia = libvlc_media_new_location(mLibVLC, mURL.c_str()); + if (!mLibVLCMedia) + { + mLibVLCMediaPlayer = 0; + setStatus(STATUS_ERROR); + return; + } + + mLibVLCMediaPlayer = libvlc_media_player_new_from_media(mLibVLCMedia); + if (!mLibVLCMediaPlayer) + { + setStatus(STATUS_ERROR); + return; + } + + // listen to events + libvlc_event_manager_t* em = libvlc_media_player_event_manager(mLibVLCMediaPlayer); + if (em) + { + libvlc_event_attach(em, libvlc_MediaPlayerOpening, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerPlaying, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerPaused, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerStopped, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerEndReached, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, this); + } + + libvlc_video_set_callbacks(mLibVLCMediaPlayer, lock, unlock, display, &mLibVLCCallbackContext); + libvlc_video_set_format(mLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth); + + mLibVLCCallbackContext.parent = this; + mLibVLCCallbackContext.texture_pixels = mPixels; + mLibVLCCallbackContext.mp = mLibVLCMediaPlayer; + + // Send a "navigate begin" event. + // This is really a browser message but the QuickTime plugin did it and + // the media system relies on this message to update internal state so we must send it too + // Note: see "navigate_complete" message below too + // https://jira.secondlife.com/browse/MAINT-6528 + LLPluginMessage message_begin(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); + message_begin.setValue("uri", mURL); + message_begin.setValueBoolean("history_back_available", false); + message_begin.setValueBoolean("history_forward_available", false); + sendMessage(message_begin); + + // volume level gets set before VLC is initialized (thanks media system) so we have to record + // it in mCurVolume and set it again here so that volume levels are correctly initialized + setVolume(mCurVolume); + + setStatus(STATUS_LOADED); + + // note this relies on the "set_loop" message arriving before the "start" (play) one + // but that appears to always be the case + if (mIsLooping) + { + libvlc_media_add_option(mLibVLCMedia, "input-repeat=65535"); + } + + libvlc_media_player_play(mLibVLCMediaPlayer); + + // send a "location_changed" message - this informs the media system + // that a new URL is the 'current' one and is used extensively. + // Again, this is really a browser message but we will use it here. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); + message.setValue("uri", mURL); + sendMessage(message); + + // Send a "navigate complete" event. + // This is really a browser message but the QuickTime plugin did it and + // the media system relies on this message to update internal state so we must send it too + // Note: see "navigate_begin" message above too + // https://jira.secondlife.com/browse/MAINT-6528 + LLPluginMessage message_complete(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); + message_complete.setValue("uri", mURL); + message_complete.setValueS32("result_code", 200); + message_complete.setValue("result_string", "OK"); + sendMessage(message_complete); } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginLibVLC::updateTitle(const char* title) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); - message.setValue("name", title); - sendMessage(message); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", title); + sendMessage(message); } void MediaPluginLibVLC::setVolumeVLC() { - if (mLibVLCMediaPlayer) - { - int vlc_vol = (int)(mCurVolume * 100); - - int result = libvlc_audio_set_volume(mLibVLCMediaPlayer, vlc_vol); - if (result == 0) - { - // volume change was accepted by LibVLC - } - else - { - // volume change was NOT accepted by LibVLC and not actioned - } + if (mLibVLCMediaPlayer) + { + int vlc_vol = (int)(mCurVolume * 100); + + int result = libvlc_audio_set_volume(mLibVLCMediaPlayer, vlc_vol); + if (result == 0) + { + // volume change was accepted by LibVLC + } + else + { + // volume change was NOT accepted by LibVLC and not actioned + } #if LL_WINDOWS - // https ://jira.secondlife.com/browse/MAINT-8119 - // CEF media plugin uses code in media_plugins/cef/windows_volume_catcher.cpp to - // set the actual output volume of the plugin process since there is no API in - // CEF to otherwise do this. - // There are explicit calls to change the volume in LibVLC but sometimes they - // are ignored SLPlugin.exe process volume is set to 0 so you never heard audio - // from the VLC media stream. - // The right way to solve this is to move the volume catcher stuff out of - // the CEF plugin and into it's own folder under media_plugins and have it referenced - // by both CEF and VLC. That's for later. The code there boils down to this so for + // https ://jira.secondlife.com/browse/MAINT-8119 + // CEF media plugin uses code in media_plugins/cef/windows_volume_catcher.cpp to + // set the actual output volume of the plugin process since there is no API in + // CEF to otherwise do this. + // There are explicit calls to change the volume in LibVLC but sometimes they + // are ignored SLPlugin.exe process volume is set to 0 so you never heard audio + // from the VLC media stream. + // The right way to solve this is to move the volume catcher stuff out of + // the CEF plugin and into it's own folder under media_plugins and have it referenced + // by both CEF and VLC. That's for later. The code there boils down to this so for // now, as we approach a release, the less risky option is to do it directly vs // calls to volume catcher code. - DWORD left_channel = (DWORD)(mCurVolume * 65535.0f); - DWORD right_channel = (DWORD)(mCurVolume * 65535.0f); - DWORD hw_volume = left_channel << 16 | right_channel; - waveOutSetVolume(NULL, hw_volume); + DWORD left_channel = (DWORD)(mCurVolume * 65535.0f); + DWORD right_channel = (DWORD)(mCurVolume * 65535.0f); + DWORD hw_volume = left_channel << 16 | right_channel; + waveOutSetVolume(NULL, hw_volume); #endif - } - else - { - // volume change was requested but VLC wasn't ready. - // that's okay though because we saved the value in mCurVolume and - // the next volume change after the VLC system is initilzied will set it - } + } + else + { + // volume change was requested but VLC wasn't ready. + // that's okay though because we saved the value in mCurVolume and + // the next volume change after the VLC system is initilzied will set it + } } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginLibVLC::setVolume(const F64 volume) { - mCurVolume = volume; + mCurVolume = volume; - setVolumeVLC(); + setVolumeVLC(); } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginLibVLC::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") - { - initVLC(); - - 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_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; - message.setValueLLSD("versions", versions); - - std::ostringstream s; - s << "LibVLC plugin "; - s << LIBVLC_VERSION_MAJOR; - s << "."; - s << LIBVLC_VERSION_MINOR; - s << "."; - s << LIBVLC_VERSION_REVISION; - - message.setValue("plugin_version", s.str()); - sendMessage(message); - } - else if (message_name == "idle") - { - setStatus(mVlcStatus); - } - else if (message_name == "cleanup") - { - resetVLC(); - } - else if (message_name == "force_exit") - { - mDeleteMe = true; - } - else if (message_name == "shm_added") - { - SharedSegmentInfo info; - info.mAddress = message_in.getValuePointer("address"); - info.mSize = (size_t)message_in.getValueS32("size"); - std::string name = message_in.getValue("name"); - - mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - - } - else if (message_name == "shm_remove") - { - std::string name = message_in.getValue("name"); - - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if (iter != mSharedSegments.end()) - { - if (mPixels == iter->second.mAddress) - { - libvlc_media_player_stop(mLibVLCMediaPlayer); - libvlc_media_player_release(mLibVLCMediaPlayer); - mLibVLCMediaPlayer = 0; - - 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") - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); - message.setValueS32("default_width", 1024); - message.setValueS32("default_height", 1024); - message.setValueS32("depth", mDepth); - message.setValueU32("internalformat", GL_RGB); - message.setValueU32("format", GL_BGRA_EXT); - 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_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") + { + initVLC(); + + 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_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; + message.setValueLLSD("versions", versions); + + std::ostringstream s; + s << "LibVLC plugin "; + s << LIBVLC_VERSION_MAJOR; + s << "."; + s << LIBVLC_VERSION_MINOR; + s << "."; + s << LIBVLC_VERSION_REVISION; + + message.setValue("plugin_version", s.str()); + sendMessage(message); + } + else if (message_name == "idle") + { + setStatus(mVlcStatus); + } + else if (message_name == "cleanup") + { + resetVLC(); + } + else if (message_name == "force_exit") + { + mDeleteMe = true; + } + else if (message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if (message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if (iter != mSharedSegments.end()) + { + if (mPixels == iter->second.mAddress) + { + libvlc_media_player_stop(mLibVLCMediaPlayer); + libvlc_media_player_release(mLibVLCMediaPlayer); + mLibVLCMediaPlayer = 0; + + 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") + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + message.setValueS32("default_width", 1024); + message.setValueS32("default_height", 1024); + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGB); + message.setValueU32("format", GL_BGRA_EXT); + 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; libvlc_time_t time = 1000.0 * mCurTime; - playMedia(); + playMedia(); if (mLibVLCMediaPlayer) { @@ -603,37 +603,37 @@ void MediaPluginLibVLC::receiveMessage(const char* message_string) mCurTime = (F64)time / 1000.0; } } - }; - }; - - 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") - { - mURL = message_in.getValue("uri"); - playMedia(); - } - } - else - if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) - { - if (message_name == "stop") - { - if (mLibVLCMediaPlayer) - { - libvlc_media_player_stop(mLibVLCMediaPlayer); - } - } - else if (message_name == "start") - { - if (mLibVLCMediaPlayer) - { + }; + }; + + 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") + { + mURL = message_in.getValue("uri"); + playMedia(); + } + } + else + if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) + { + if (message_name == "stop") + { + if (mLibVLCMediaPlayer) + { + libvlc_media_player_stop(mLibVLCMediaPlayer); + } + } + else if (message_name == "start") + { + if (mLibVLCMediaPlayer) + { if (mVlcStatus == STATUS_DONE && !libvlc_media_player_is_playing(mLibVLCMediaPlayer)) { // stop or vlc will ignore 'play', it will just @@ -641,18 +641,18 @@ void MediaPluginLibVLC::receiveMessage(const char* message_string) // seek was used libvlc_media_player_stop(mLibVLCMediaPlayer); } - libvlc_media_player_play(mLibVLCMediaPlayer); - } - } - else if (message_name == "pause") - { - if (mLibVLCMediaPlayer) - { - libvlc_media_player_set_pause(mLibVLCMediaPlayer, 1); - } - } - else if (message_name == "seek") - { + libvlc_media_player_play(mLibVLCMediaPlayer); + } + } + else if (message_name == "pause") + { + if (mLibVLCMediaPlayer) + { + libvlc_media_player_set_pause(mLibVLCMediaPlayer, 1); + } + } + else if (message_name == "seek") + { if (mLibVLCMediaPlayer) { libvlc_time_t time = 1000.0 * message_in.getValueReal("time"); @@ -674,43 +674,43 @@ void MediaPluginLibVLC::receiveMessage(const char* message_string) setDurationDirty(); } } - } - else if (message_name == "set_loop") - { - bool loop = message_in.getValueBoolean("loop"); - mIsLooping = loop; - } - else if (message_name == "set_volume") - { - // volume comes in 0 -> 1.0 - F64 volume = message_in.getValueReal("volume"); - setVolume(volume); - } - } - } + } + else if (message_name == "set_loop") + { + bool loop = message_in.getValueBoolean("loop"); + mIsLooping = loop; + } + else if (message_name == "set_volume") + { + // volume comes in 0 -> 1.0 + F64 volume = message_in.getValueReal("volume"); + setVolume(volume); + } + } + } } //////////////////////////////////////////////////////////////////////////////// // bool MediaPluginLibVLC::init() { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); - message.setValue("name", "LibVLC Plugin"); - sendMessage(message); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", "LibVLC Plugin"); + sendMessage(message); - return true; + return true; }; //////////////////////////////////////////////////////////////////////////////// // int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, - void* host_user_data, - LLPluginInstance::sendMessageFunction *plugin_send_func, - void **plugin_user_data) + void* host_user_data, + LLPluginInstance::sendMessageFunction *plugin_send_func, + void **plugin_user_data) { - MediaPluginLibVLC* self = new MediaPluginLibVLC(host_send_func, host_user_data); - *plugin_send_func = MediaPluginLibVLC::staticReceiveMessage; - *plugin_user_data = (void*)self; + MediaPluginLibVLC* self = new MediaPluginLibVLC(host_send_func, host_user_data); + *plugin_send_func = MediaPluginLibVLC::staticReceiveMessage; + *plugin_user_data = (void*)self; - return 0; + return 0; } |