summaryrefslogtreecommitdiff
path: root/indra/media_plugins
diff options
context:
space:
mode:
Diffstat (limited to 'indra/media_plugins')
-rw-r--r--indra/media_plugins/CMakeLists.txt4
-rw-r--r--indra/media_plugins/base/media_plugin_base.cpp41
-rw-r--r--indra/media_plugins/base/media_plugin_base.h41
-rw-r--r--indra/media_plugins/example/media_plugin_example.cpp67
-rw-r--r--indra/media_plugins/gstreamer010/CMakeLists.txt6
-rw-r--r--indra/media_plugins/gstreamer010/llmediaimplgstreamer.h36
-rw-r--r--indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp36
-rw-r--r--indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h36
-rw-r--r--indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h36
-rw-r--r--indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp36
-rw-r--r--indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h36
-rw-r--r--indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp167
-rw-r--r--indra/media_plugins/quicktime/media_plugin_quicktime.cpp111
-rw-r--r--indra/media_plugins/webkit/CMakeLists.txt51
-rw-r--r--indra/media_plugins/webkit/dummy_volume_catcher.cpp58
-rw-r--r--indra/media_plugins/webkit/linux_volume_catcher.cpp468
-rw-r--r--indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc21
-rw-r--r--indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc6
-rw-r--r--indra/media_plugins/webkit/mac_volume_catcher.cpp268
-rw-r--r--indra/media_plugins/webkit/media_plugin_webkit.cpp555
-rw-r--r--indra/media_plugins/webkit/volume_catcher.h54
-rw-r--r--indra/media_plugins/webkit/windows_volume_catcher.cpp117
-rw-r--r--indra/media_plugins/winmmshim/CMakeLists.txt34
-rw-r--r--indra/media_plugins/winmmshim/forwarding_api.cpp1454
-rw-r--r--indra/media_plugins/winmmshim/forwarding_api.h389
-rw-r--r--indra/media_plugins/winmmshim/winmm.def218
-rw-r--r--indra/media_plugins/winmmshim/winmm_shim.cpp188
27 files changed, 4010 insertions, 524 deletions
diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt
index cc03d9cb72..85318aea3b 100644
--- a/indra/media_plugins/CMakeLists.txt
+++ b/indra/media_plugins/CMakeLists.txt
@@ -10,4 +10,8 @@ if (WINDOWS OR DARWIN)
add_subdirectory(quicktime)
endif (WINDOWS OR DARWIN)
+if (WINDOWS)
+ add_subdirectory(winmmshim)
+endif (WINDOWS)
+
add_subdirectory(example)
diff --git a/indra/media_plugins/base/media_plugin_base.cpp b/indra/media_plugins/base/media_plugin_base.cpp
index 658783e064..37c498664a 100644
--- a/indra/media_plugins/base/media_plugin_base.cpp
+++ b/indra/media_plugins/base/media_plugin_base.cpp
@@ -5,30 +5,25 @@
* All plugins should be a subclass of MediaPluginBase.
*
* @cond
- * $LicenseInfo:firstyear=2008&license=viewergpl$
- *
- * Copyright (c) 2008, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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
*/
diff --git a/indra/media_plugins/base/media_plugin_base.h b/indra/media_plugins/base/media_plugin_base.h
index ed4dc0cfa9..38b8226bb3 100644
--- a/indra/media_plugins/base/media_plugin_base.h
+++ b/indra/media_plugins/base/media_plugin_base.h
@@ -3,30 +3,25 @@
* @brief Media plugin base class for LLMedia API plugin system
*
* @cond
- * $LicenseInfo:firstyear=2008&license=viewergpl$
- *
- * Copyright (c) 2008, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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
*/
diff --git a/indra/media_plugins/example/media_plugin_example.cpp b/indra/media_plugins/example/media_plugin_example.cpp
index f5b077fea0..f8a871930e 100644
--- a/indra/media_plugins/example/media_plugin_example.cpp
+++ b/indra/media_plugins/example/media_plugin_example.cpp
@@ -3,30 +3,25 @@
* @brief Example plugin for LLMedia API plugin system
*
* @cond
- * $LicenseInfo:firstyear=2008&license=viewergpl$
- *
- * Copyright (c) 2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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
*/
@@ -119,17 +114,6 @@ void MediaPluginExample::receiveMessage( const char* message_string )
std::string plugin_version = "Example media plugin, Example Version 1.0.0.0";
message.setValue( "plugin_version", plugin_version );
sendMessage( message );
-
- // Plugin gets to decide the texture parameters to use.
- message.setMessage( LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params" );
- message.setValueS32( "default_width", mWidth );
- message.setValueS32( "default_height", mHeight );
- message.setValueS32( "depth", mDepth );
- message.setValueU32( "internalformat", GL_RGBA );
- message.setValueU32( "format", GL_RGBA );
- message.setValueU32( "type", GL_UNSIGNED_BYTE );
- message.setValueBoolean( "coords_opengl", false );
- sendMessage( message );
}
else
if ( message_name == "idle" )
@@ -191,7 +175,20 @@ void MediaPluginExample::receiveMessage( const char* message_string )
else
if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA )
{
- if ( message_name == "size_change" )
+ if ( message_name == "init" )
+ {
+ // Plugin gets to decide the texture parameters to use.
+ LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params" );
+ message.setValueS32( "default_width", mWidth );
+ message.setValueS32( "default_height", mHeight );
+ message.setValueS32( "depth", mDepth );
+ message.setValueU32( "internalformat", GL_RGBA );
+ message.setValueU32( "format", GL_RGBA );
+ message.setValueU32( "type", GL_UNSIGNED_BYTE );
+ message.setValueBoolean( "coords_opengl", false );
+ sendMessage( message );
+ }
+ else if ( message_name == "size_change" )
{
std::string name = message_in.getValue( "name" );
S32 width = message_in.getValueS32( "width" );
diff --git a/indra/media_plugins/gstreamer010/CMakeLists.txt b/indra/media_plugins/gstreamer010/CMakeLists.txt
index ba66166c55..9bb5da7974 100644
--- a/indra/media_plugins/gstreamer010/CMakeLists.txt
+++ b/indra/media_plugins/gstreamer010/CMakeLists.txt
@@ -50,12 +50,12 @@ set(media_plugin_gstreamer010_HEADER_FILES
llmediaimplgstreamertriviallogging.h
)
-if (${CXX_VERSION_NUMBER} MATCHES "4[23].")
+if (${CXX_VERSION_NUMBER} MATCHES "4[23456789].")
# Work around a bad interaction between broken gstreamer headers and
- # g++ 4.3's increased strictness.
+ # g++ >= 4.2's increased strictness.
set_source_files_properties(llmediaimplgstreamervidplug.cpp PROPERTIES
COMPILE_FLAGS -Wno-write-strings)
-endif (${CXX_VERSION_NUMBER} MATCHES "4[23].")
+endif (${CXX_VERSION_NUMBER} MATCHES "4[23456789].")
add_library(media_plugin_gstreamer010
SHARED
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h
index 48accd3e66..6bc272c009 100644
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h
@@ -4,31 +4,25 @@
* @brief implementation that supports media playback via GStreamer.
*
* @cond
- * $LicenseInfo:firstyear=2007&license=viewergpl$
- *
- * Copyright (c) 2007-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
*/
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp
index 52cea46d46..2e4baaa9eb 100644
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp
@@ -3,31 +3,25 @@
* @brief dynamic GStreamer symbol-grabbing code
*
* @cond
- * $LicenseInfo:firstyear=2007&license=viewergpl$
- *
- * Copyright (c) 2007-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
*/
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h
index 88f100af6e..d1559089c8 100644
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h
@@ -3,31 +3,25 @@
* @brief dynamic GStreamer symbol-grabbing code
*
* @cond
- * $LicenseInfo:firstyear=2007&license=viewergpl$
- *
- * Copyright (c) 2007-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
*/
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h
index 799808aa8b..e7b31bec94 100644
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h
@@ -3,31 +3,25 @@
* @brief minimal logging utilities.
*
* @cond
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- *
- * Copyright (c) 2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
*/
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
index 484948bd9f..a51a8aa9e1 100644
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
@@ -3,31 +3,25 @@
* @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl
*
* @cond
- * $LicenseInfo:firstyear=2007&license=viewergpl$
- *
- * Copyright (c) 2007-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
*/
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
index 8f1cf84978..29d65fa4e9 100644
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
@@ -3,31 +3,25 @@
* @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl
*
* @cond
- * $LicenseInfo:firstyear=2007&license=viewergpl$
- *
- * Copyright (c) 2007-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
*/
diff --git a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
index 26173314a7..352b63583e 100644
--- a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
+++ b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
@@ -3,30 +3,25 @@
* @brief GStreamer-0.10 plugin for LLMedia API plugin system
*
* @cond
- * $LicenseInfo:firstyear=2007&license=viewergpl$
- *
- * Copyright (c) 2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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
*/
@@ -141,6 +136,7 @@ private:
// Very GStreamer-specific
GMainLoop *mPump; // event pump for this media
GstElement *mPlaybin;
+ GstElement *mVisualizer;
GstSLVideo *mVideoSink;
};
@@ -159,6 +155,7 @@ MediaPluginGStreamer010::MediaPluginGStreamer010(
mSeekDestination(0.0),
mPump ( NULL ),
mPlaybin ( NULL ),
+ mVisualizer ( NULL ),
mVideoSink ( NULL ),
mCommand ( COMMAND_NONE )
{
@@ -542,8 +539,12 @@ MediaPluginGStreamer010::pause()
{
DEBUGMSG("pausing media...");
// todo: error-check this?
- llgst_element_set_state(mPlaybin, GST_STATE_PAUSED);
- return true;
+ if (mDoneInit && mPlaybin)
+ {
+ llgst_element_set_state(mPlaybin, GST_STATE_PAUSED);
+ return true;
+ }
+ return false;
}
bool
@@ -551,8 +552,12 @@ MediaPluginGStreamer010::stop()
{
DEBUGMSG("stopping media...");
// todo: error-check this?
- llgst_element_set_state(mPlaybin, GST_STATE_READY);
- return true;
+ if (mDoneInit && mPlaybin)
+ {
+ llgst_element_set_state(mPlaybin, GST_STATE_READY);
+ return true;
+ }
+ return false;
}
bool
@@ -562,8 +567,12 @@ MediaPluginGStreamer010::play(double rate)
DEBUGMSG("playing media... rate=%f", rate);
// todo: error-check this?
- llgst_element_set_state(mPlaybin, GST_STATE_PLAYING);
- return true;
+ if (mDoneInit && mPlaybin)
+ {
+ llgst_element_set_state(mPlaybin, GST_STATE_PLAYING);
+ return true;
+ }
+ return false;
}
bool
@@ -606,7 +615,7 @@ bool
MediaPluginGStreamer010::getTimePos(double &sec_out)
{
bool got_position = false;
- if (mPlaybin)
+ if (mDoneInit && mPlaybin)
{
gint64 pos;
GstFormat timefmt = GST_FORMAT_TIME;
@@ -686,6 +695,35 @@ MediaPluginGStreamer010::load()
this);
llgst_object_unref (bus);
+#if 0 // not quite stable/correct yet
+ // get a visualizer element (bonus feature!)
+ char* vis_name = getenv("LL_GST_VIS_NAME");
+ if (!vis_name ||
+ (vis_name && std::string(vis_name)!="none"))
+ {
+ if (vis_name)
+ {
+ mVisualizer = llgst_element_factory_make (vis_name, "vis");
+ }
+ if (!mVisualizer)
+ {
+ mVisualizer = llgst_element_factory_make ("libvisual_jess", "vis");
+ if (!mVisualizer)
+ {
+ mVisualizer = llgst_element_factory_make ("goom", "vis");
+ if (!mVisualizer)
+ {
+ mVisualizer = llgst_element_factory_make ("libvisual_lv_scope", "vis");
+ if (!mVisualizer)
+ {
+ // That's okay, we don't NEED this.
+ }
+ }
+ }
+ }
+ }
+#endif
+
if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) {
// instantiate a custom video sink
mVideoSink =
@@ -702,6 +740,11 @@ MediaPluginGStreamer010::load()
g_object_set(mPlaybin, "video-sink", mVideoSink, NULL);
}
+ if (mVisualizer)
+ {
+ g_object_set(mPlaybin, "vis-plugin", mVisualizer, NULL);
+ }
+
return true;
}
@@ -724,6 +767,12 @@ MediaPluginGStreamer010::unload ()
mPlaybin = NULL;
}
+ if (mVisualizer)
+ {
+ llgst_object_unref (GST_OBJECT (mVisualizer));
+ mVisualizer = NULL;
+ }
+
if (mPump)
{
g_main_loop_quit(mPump);
@@ -946,33 +995,6 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string)
message.setValue("plugin_version", getVersion());
sendMessage(message);
-
- // Plugin gets to decide the texture parameters to use.
- message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
- // lame to have to decide this now, it depends on the movie. Oh well.
- mDepth = 4;
-
- mCurrentWidth = 1;
- mCurrentHeight = 1;
- mPreviousWidth = 1;
- mPreviousHeight = 1;
- mNaturalWidth = 1;
- mNaturalHeight = 1;
- mWidth = 1;
- mHeight = 1;
- mTextureWidth = 1;
- mTextureHeight = 1;
-
- message.setValueU32("format", GL_RGBA);
- message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV);
-
- message.setValueS32("depth", mDepth);
- message.setValueS32("default_width", mWidth);
- message.setValueS32("default_height", mHeight);
- message.setValueU32("internalformat", GL_RGBA8);
- message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left.
- message.setValueBoolean("allow_downsample", true); // we respond with grace and performance if asked to downscale
- sendMessage(message);
}
else if(message_name == "idle")
{
@@ -1037,7 +1059,36 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string)
}
else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
{
- if(message_name == "size_change")
+ if(message_name == "init")
+ {
+ // Plugin gets to decide the texture parameters to use.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
+ // lame to have to decide this now, it depends on the movie. Oh well.
+ mDepth = 4;
+
+ mCurrentWidth = 1;
+ mCurrentHeight = 1;
+ mPreviousWidth = 1;
+ mPreviousHeight = 1;
+ mNaturalWidth = 1;
+ mNaturalHeight = 1;
+ mWidth = 1;
+ mHeight = 1;
+ mTextureWidth = 1;
+ mTextureHeight = 1;
+
+ message.setValueU32("format", GL_RGBA);
+ message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV);
+
+ message.setValueS32("depth", mDepth);
+ message.setValueS32("default_width", mWidth);
+ message.setValueS32("default_height", mHeight);
+ message.setValueU32("internalformat", GL_RGBA8);
+ message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left.
+ message.setValueBoolean("allow_downsample", true); // we respond with grace and performance if asked to downscale
+ sendMessage(message);
+ }
+ else if(message_name == "size_change")
{
std::string name = message_in.getValue("name");
S32 width = message_in.getValueS32("width");
diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
index dbc44c8334..999f754dcf 100644
--- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
+++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
@@ -3,30 +3,25 @@
* @brief QuickTime plugin for LLMedia API plugin system
*
* @cond
- * $LicenseInfo:firstyear=2008&license=viewergpl$
- *
- * Copyright (c) 2008, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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
*/
@@ -724,8 +719,8 @@ private:
return false;
// allocate some space and grab it
- UInt8* item_data = new UInt8( size + 1 );
- memset( item_data, 0, ( size + 1 ) * sizeof( UInt8* ) );
+ UInt8* item_data = new UInt8[ size + 1 ];
+ memset( item_data, 0, ( size + 1 ) * sizeof( UInt8 ) );
result = QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL );
if ( noErr != result )
{
@@ -859,36 +854,6 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
plugin_version += codec.str();
message.setValue("plugin_version", plugin_version);
sendMessage(message);
-
- // Plugin gets to decide the texture parameters to use.
- message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
- #if defined(LL_WINDOWS)
- // Values for Windows
- mDepth = 3;
- message.setValueU32("format", GL_RGB);
- message.setValueU32("type", GL_UNSIGNED_BYTE);
-
- // We really want to pad the texture width to a multiple of 32 bytes, but since we're using 3-byte pixels, it doesn't come out even.
- // Padding to a multiple of 3*32 guarantees it'll divide out properly.
- message.setValueU32("padding", 32 * 3);
- #else
- // Values for Mac
- mDepth = 4;
- message.setValueU32("format", GL_BGRA_EXT);
- #ifdef __BIG_ENDIAN__
- message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV );
- #else
- message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8);
- #endif
-
- // Pad texture width to a multiple of 32 bytes, to line up with cache lines.
- message.setValueU32("padding", 32);
- #endif
- message.setValueS32("depth", mDepth);
- message.setValueU32("internalformat", GL_RGB);
- message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left.
- message.setValueBoolean("allow_downsample", true);
- sendMessage(message);
}
else if(message_name == "idle")
{
@@ -953,7 +918,41 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
}
else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
{
- if(message_name == "size_change")
+ if(message_name == "init")
+ {
+ // This is the media init message -- all necessary data for initialization should have been received.
+
+ // Plugin gets to decide the texture parameters to use.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
+ #if defined(LL_WINDOWS)
+ // Values for Windows
+ mDepth = 3;
+ message.setValueU32("format", GL_RGB);
+ message.setValueU32("type", GL_UNSIGNED_BYTE);
+
+ // We really want to pad the texture width to a multiple of 32 bytes, but since we're using 3-byte pixels, it doesn't come out even.
+ // Padding to a multiple of 3*32 guarantees it'll divide out properly.
+ message.setValueU32("padding", 32 * 3);
+ #else
+ // Values for Mac
+ mDepth = 4;
+ message.setValueU32("format", GL_BGRA_EXT);
+ #ifdef __BIG_ENDIAN__
+ message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV );
+ #else
+ message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8);
+ #endif
+
+ // Pad texture width to a multiple of 32 bytes, to line up with cache lines.
+ message.setValueU32("padding", 32);
+ #endif
+ message.setValueS32("depth", mDepth);
+ message.setValueU32("internalformat", GL_RGB);
+ message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left.
+ message.setValueBoolean("allow_downsample", true);
+ sendMessage(message);
+ }
+ else if(message_name == "size_change")
{
std::string name = message_in.getValue("name");
S32 width = message_in.getValueS32("width");
diff --git a/indra/media_plugins/webkit/CMakeLists.txt b/indra/media_plugins/webkit/CMakeLists.txt
index 673e059c34..3a1df13645 100644
--- a/indra/media_plugins/webkit/CMakeLists.txt
+++ b/indra/media_plugins/webkit/CMakeLists.txt
@@ -9,14 +9,17 @@ include(LLPlugin)
include(LLMath)
include(LLRender)
include(LLWindow)
+include(UI)
include(Linking)
include(PluginAPI)
include(MediaPluginBase)
include(FindOpenGL)
+include(PulseAudio)
include(WebKitLibPlugin)
include_directories(
+ ${PULSEAUDIO_INCLUDE_DIRS}
${LLPLUGIN_INCLUDE_DIRS}
${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
@@ -41,19 +44,54 @@ set(media_plugin_webkit_SOURCE_FILES
media_plugin_webkit.cpp
)
-add_library(media_plugin_webkit
- SHARED
- ${media_plugin_webkit_SOURCE_FILES}
-)
+set(media_plugin_webkit_HEADER_FILES
+ volume_catcher.h
+ )
-target_link_libraries(media_plugin_webkit
+set(media_plugin_webkit_LINK_LIBRARIES
${LLPLUGIN_LIBRARIES}
${MEDIA_PLUGIN_BASE_LIBRARIES}
${LLCOMMON_LIBRARIES}
${WEBKIT_PLUGIN_LIBRARIES}
${PLUGIN_API_WINDOWS_LIBRARIES}
+ ${PULSEAUDIO_LIBRARIES}
)
+# Select which VolumeCatcher implementation to use
+if (LINUX)
+ if (PULSEAUDIO)
+ list(APPEND media_plugin_webkit_SOURCE_FILES linux_volume_catcher.cpp)
+ endif (PULSEAUDIO)
+ list(APPEND media_plugin_webkit_LINK_LIBRARIES
+ ${UI_LIBRARIES} # for glib/GTK
+ )
+elseif (DARWIN)
+ list(APPEND media_plugin_webkit_SOURCE_FILES mac_volume_catcher.cpp)
+ find_library(CORESERVICES_LIBRARY CoreServices)
+ find_library(AUDIOUNIT_LIBRARY AudioUnit)
+ list(APPEND media_plugin_webkit_LINK_LIBRARIES
+ ${CORESERVICES_LIBRARY} # for Component Manager calls
+ ${AUDIOUNIT_LIBRARY} # for AudioUnit calls
+ )
+elseif (WINDOWS)
+ list(APPEND media_plugin_webkit_SOURCE_FILES windows_volume_catcher.cpp)
+else (LINUX)
+ # All other platforms use the dummy volume catcher for now.
+ list(APPEND media_plugin_webkit_SOURCE_FILES dummy_volume_catcher.cpp)
+endif (LINUX)
+
+set_source_files_properties(${media_plugin_webkit_HEADER_FILES}
+ PROPERTIES HEADER_FILE_ONLY TRUE)
+
+list(APPEND media_plugin_webkit_SOURCE_FILES ${media_plugin_webkit_HEADER_FILES})
+
+add_library(media_plugin_webkit
+ SHARED
+ ${media_plugin_webkit_SOURCE_FILES}
+)
+
+target_link_libraries(media_plugin_webkit ${media_plugin_webkit_LINK_LIBRARIES})
+
add_dependencies(media_plugin_webkit
${LLPLUGIN_LIBRARIES}
${MEDIA_PLUGIN_BASE_LIBRARIES}
@@ -87,4 +125,5 @@ if (DARWIN)
DEPENDS media_plugin_webkit ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib
)
-endif (DARWIN) \ No newline at end of file
+endif (DARWIN)
+
diff --git a/indra/media_plugins/webkit/dummy_volume_catcher.cpp b/indra/media_plugins/webkit/dummy_volume_catcher.cpp
new file mode 100644
index 0000000000..d54b31b2ae
--- /dev/null
+++ b/indra/media_plugins/webkit/dummy_volume_catcher.cpp
@@ -0,0 +1,58 @@
+/**
+ * @file dummy_volume_catcher.cpp
+ * @brief A null implementation of the "VolumeCatcher" class for platforms where it's not implemented yet.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "volume_catcher.h"
+
+
+class VolumeCatcherImpl
+{
+};
+
+/////////////////////////////////////////////////////
+
+VolumeCatcher::VolumeCatcher()
+{
+ pimpl = NULL;
+}
+
+VolumeCatcher::~VolumeCatcher()
+{
+}
+
+void VolumeCatcher::setVolume(F32 volume)
+{
+}
+
+void VolumeCatcher::setPan(F32 pan)
+{
+}
+
+void VolumeCatcher::pump()
+{
+}
+
diff --git a/indra/media_plugins/webkit/linux_volume_catcher.cpp b/indra/media_plugins/webkit/linux_volume_catcher.cpp
new file mode 100644
index 0000000000..91be3a89e9
--- /dev/null
+++ b/indra/media_plugins/webkit/linux_volume_catcher.cpp
@@ -0,0 +1,468 @@
+/**
+ * @file linux_volume_catcher.cpp
+ * @brief A Linux-specific, PulseAudio-specific hack to detect and volume-adjust new audio sources
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+/*
+ The high-level design is as follows:
+ 1) Connect to the PulseAudio daemon
+ 2) Watch for the creation of new audio players connecting to the daemon (this includes ALSA clients running on the PulseAudio emulation layer, such as Flash plugins)
+ 3) Examine any new audio player's PID to see if it belongs to our own process
+ 4) If so, tell PA to adjust the volume of that audio player ('sink input' in PA parlance)
+ 5) Keep a list of all living audio players that we care about, adjust the volumes of all of them when we get a new setVolume() call
+ */
+
+#include "linden_common.h"
+
+#include "volume_catcher.h"
+
+
+extern "C" {
+#include <glib.h>
+#include <glib-object.h>
+
+#include <pulse/introspect.h>
+#include <pulse/context.h>
+#include <pulse/subscribe.h>
+#include <pulse/glib-mainloop.h> // There's no special reason why we want the *glib* PA mainloop, but the generic polling implementation seems broken.
+
+#include "apr_pools.h"
+#include "apr_dso.h"
+}
+
+////////////////////////////////////////////////////
+
+#define DEBUGMSG(...) do {} while(0)
+#define INFOMSG(...) do {} while(0)
+#define WARNMSG(...) do {} while(0)
+
+#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) RTN (*ll##PASYM)(__VA_ARGS__) = NULL
+#include "linux_volume_catcher_pa_syms.inc"
+#include "linux_volume_catcher_paglib_syms.inc"
+#undef LL_PA_SYM
+
+static bool sSymsGrabbed = false;
+static apr_pool_t *sSymPADSOMemoryPool = NULL;
+static apr_dso_handle_t *sSymPADSOHandleG = NULL;
+
+bool grab_pa_syms(std::string pulse_dso_name)
+{
+ if (sSymsGrabbed)
+ {
+ // already have grabbed good syms
+ return true;
+ }
+
+ bool sym_error = false;
+ bool rtn = false;
+ apr_status_t rv;
+ apr_dso_handle_t *sSymPADSOHandle = NULL;
+
+#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##PASYM, sSymPADSOHandle, #PASYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #PASYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #PASYM, (void*)ll##PASYM);}while(0)
+
+ //attempt to load the shared library
+ apr_pool_create(&sSymPADSOMemoryPool, NULL);
+
+ if ( APR_SUCCESS == (rv = apr_dso_load(&sSymPADSOHandle,
+ pulse_dso_name.c_str(),
+ sSymPADSOMemoryPool) ))
+ {
+ INFOMSG("Found DSO: %s", pulse_dso_name.c_str());
+
+#include "linux_volume_catcher_pa_syms.inc"
+#include "linux_volume_catcher_paglib_syms.inc"
+
+ if ( sSymPADSOHandle )
+ {
+ sSymPADSOHandleG = sSymPADSOHandle;
+ sSymPADSOHandle = NULL;
+ }
+
+ rtn = !sym_error;
+ }
+ else
+ {
+ INFOMSG("Couldn't load DSO: %s", pulse_dso_name.c_str());
+ rtn = false; // failure
+ }
+
+ if (sym_error)
+ {
+ WARNMSG("Failed to find necessary symbols in PulseAudio libraries.");
+ }
+#undef LL_PA_SYM
+
+ sSymsGrabbed = rtn;
+ return rtn;
+}
+
+
+void ungrab_pa_syms()
+{
+ // should be safe to call regardless of whether we've
+ // actually grabbed syms.
+
+ if ( sSymPADSOHandleG )
+ {
+ apr_dso_unload(sSymPADSOHandleG);
+ sSymPADSOHandleG = NULL;
+ }
+
+ if ( sSymPADSOMemoryPool )
+ {
+ apr_pool_destroy(sSymPADSOMemoryPool);
+ sSymPADSOMemoryPool = NULL;
+ }
+
+ // NULL-out all of the symbols we'd grabbed
+#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{ll##PASYM = NULL;}while(0)
+#include "linux_volume_catcher_pa_syms.inc"
+#include "linux_volume_catcher_paglib_syms.inc"
+#undef LL_PA_SYM
+
+ sSymsGrabbed = false;
+}
+////////////////////////////////////////////////////
+
+// PulseAudio requires a chain of callbacks with C linkage
+extern "C" {
+ void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *i, int eol, void *userdata);
+ void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata);
+ void callback_context_state(pa_context *context, void *userdata);
+}
+
+
+class VolumeCatcherImpl
+{
+public:
+ VolumeCatcherImpl();
+ ~VolumeCatcherImpl();
+
+ void setVolume(F32 volume);
+ void pump(void);
+
+ // for internal use - can't be private because used from our C callbacks
+
+ bool loadsyms(std::string pulse_dso_name);
+ void init();
+ void cleanup();
+
+ void update_all_volumes(F32 volume);
+ void update_index_volume(U32 index, F32 volume);
+ void connected_okay();
+
+ std::set<U32> mSinkInputIndices;
+ std::map<U32,U32> mSinkInputNumChannels;
+ F32 mDesiredVolume;
+ pa_glib_mainloop *mMainloop;
+ pa_context *mPAContext;
+ bool mConnected;
+ bool mGotSyms;
+};
+
+VolumeCatcherImpl::VolumeCatcherImpl()
+ : mDesiredVolume(0.0f),
+ mMainloop(NULL),
+ mPAContext(NULL),
+ mConnected(false),
+ mGotSyms(false)
+{
+ init();
+}
+
+VolumeCatcherImpl::~VolumeCatcherImpl()
+{
+ cleanup();
+}
+
+bool VolumeCatcherImpl::loadsyms(std::string pulse_dso_name)
+{
+ return grab_pa_syms(pulse_dso_name);
+}
+
+void VolumeCatcherImpl::init()
+{
+ // try to be as defensive as possible because PA's interface is a
+ // bit fragile and (for our purposes) we'd rather simply not function
+ // than crash
+
+ // we cheat and rely upon libpulse-mainloop-glib.so.0 to pull-in
+ // libpulse.so.0 - this isn't a great assumption, and the two DSOs should
+ // probably be loaded separately. Our Linux DSO framework needs refactoring,
+ // we do this sort of thing a lot with practically identical logic...
+ mGotSyms = loadsyms("libpulse-mainloop-glib.so.0");
+ if (!mGotSyms) return;
+
+ // better make double-sure glib itself is initialized properly.
+ if (!g_thread_supported ()) g_thread_init (NULL);
+ g_type_init();
+
+ mMainloop = llpa_glib_mainloop_new(g_main_context_default());
+ if (mMainloop)
+ {
+ pa_mainloop_api *api = llpa_glib_mainloop_get_api(mMainloop);
+ if (api)
+ {
+ pa_proplist *proplist = llpa_proplist_new();
+ if (proplist)
+ {
+ llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ICON_NAME, "multimedia-player");
+ llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ID, "com.secondlife.viewer.mediaplugvoladjust");
+ llpa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "SL Plugin Volume Adjuster");
+ llpa_proplist_sets(proplist, PA_PROP_APPLICATION_VERSION, "1");
+
+ // plain old pa_context_new() is broken!
+ mPAContext = llpa_context_new_with_proplist(api, NULL, proplist);
+ llpa_proplist_free(proplist);
+ }
+ }
+ }
+
+ // Now we've set up a PA context and mainloop, try connecting the
+ // PA context to a PA daemon.
+ if (mPAContext)
+ {
+ llpa_context_set_state_callback(mPAContext, callback_context_state, this);
+ pa_context_flags_t cflags = (pa_context_flags)0; // maybe add PA_CONTEXT_NOAUTOSPAWN?
+ if (llpa_context_connect(mPAContext, NULL, cflags, NULL) >= 0)
+ {
+ // Okay! We haven't definitely connected, but we
+ // haven't definitely failed yet.
+ }
+ else
+ {
+ // Failed to connect to PA manager... we'll leave
+ // things like that. Perhaps we should try again later.
+ }
+ }
+}
+
+void VolumeCatcherImpl::cleanup()
+{
+ mConnected = false;
+
+ if (mGotSyms && mPAContext)
+ {
+ llpa_context_disconnect(mPAContext);
+ llpa_context_unref(mPAContext);
+ }
+ mPAContext = NULL;
+
+ if (mGotSyms && mMainloop)
+ {
+ llpa_glib_mainloop_free(mMainloop);
+ }
+ mMainloop = NULL;
+}
+
+void VolumeCatcherImpl::setVolume(F32 volume)
+{
+ mDesiredVolume = volume;
+
+ if (!mGotSyms) return;
+
+ if (mConnected && mPAContext)
+ {
+ update_all_volumes(mDesiredVolume);
+ }
+
+ pump();
+}
+
+void VolumeCatcherImpl::pump()
+{
+ gboolean may_block = FALSE;
+ g_main_context_iteration(g_main_context_default(), may_block);
+}
+
+void VolumeCatcherImpl::connected_okay()
+{
+ pa_operation *op;
+
+ // fetch global list of existing sinkinputs
+ if ((op = llpa_context_get_sink_input_info_list(mPAContext,
+ callback_discovered_sinkinput,
+ this)))
+ {
+ llpa_operation_unref(op);
+ }
+
+ // subscribe to future global sinkinput changes
+ llpa_context_set_subscribe_callback(mPAContext,
+ callback_subscription_alert,
+ this);
+ if ((op = llpa_context_subscribe(mPAContext, (pa_subscription_mask_t)
+ (PA_SUBSCRIPTION_MASK_SINK_INPUT),
+ NULL, NULL)))
+ {
+ llpa_operation_unref(op);
+ }
+}
+
+void VolumeCatcherImpl::update_all_volumes(F32 volume)
+{
+ for (std::set<U32>::iterator it = mSinkInputIndices.begin();
+ it != mSinkInputIndices.end(); ++it)
+ {
+ update_index_volume(*it, volume);
+ }
+}
+
+void VolumeCatcherImpl::update_index_volume(U32 index, F32 volume)
+{
+ static pa_cvolume cvol;
+ llpa_cvolume_set(&cvol, mSinkInputNumChannels[index],
+ llpa_sw_volume_from_linear(volume));
+
+ pa_context *c = mPAContext;
+ uint32_t idx = index;
+ const pa_cvolume *cvolumep = &cvol;
+ pa_context_success_cb_t cb = NULL; // okay as null
+ void *userdata = NULL; // okay as null
+
+ pa_operation *op;
+ if ((op = llpa_context_set_sink_input_volume(c, idx, cvolumep, cb, userdata)))
+ {
+ llpa_operation_unref(op);
+ }
+}
+
+
+void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *sii, int eol, void *userdata)
+{
+ VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata);
+ llassert(impl);
+
+ if (0 == eol)
+ {
+ pa_proplist *proplist = sii->proplist;
+ pid_t sinkpid = atoll(llpa_proplist_gets(proplist, PA_PROP_APPLICATION_PROCESS_ID));
+
+ if (sinkpid == getpid()) // does the discovered sinkinput belong to this process?
+ {
+ bool is_new = (impl->mSinkInputIndices.find(sii->index) ==
+ impl->mSinkInputIndices.end());
+
+ impl->mSinkInputIndices.insert(sii->index);
+ impl->mSinkInputNumChannels[sii->index] = sii->channel_map.channels;
+
+ if (is_new)
+ {
+ // new!
+ impl->update_index_volume(sii->index, impl->mDesiredVolume);
+ }
+ else
+ {
+ // seen it already, do nothing.
+ }
+ }
+ }
+}
+
+void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata)
+{
+ VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata);
+ llassert(impl);
+
+ switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
+ case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
+ PA_SUBSCRIPTION_EVENT_REMOVE)
+ {
+ // forget this sinkinput, if we were caring about it
+ impl->mSinkInputIndices.erase(index);
+ impl->mSinkInputNumChannels.erase(index);
+ }
+ else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
+ PA_SUBSCRIPTION_EVENT_NEW)
+ {
+ // ask for more info about this new sinkinput
+ pa_operation *op;
+ if ((op = llpa_context_get_sink_input_info(impl->mPAContext, index, callback_discovered_sinkinput, impl)))
+ {
+ llpa_operation_unref(op);
+ }
+ }
+ else
+ {
+ // property change on this sinkinput - we don't care.
+ }
+ break;
+
+ default:;
+ }
+}
+
+void callback_context_state(pa_context *context, void *userdata)
+{
+ VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata);
+ llassert(impl);
+
+ switch (llpa_context_get_state(context))
+ {
+ case PA_CONTEXT_READY:
+ impl->mConnected = true;
+ impl->connected_okay();
+ break;
+ case PA_CONTEXT_TERMINATED:
+ impl->mConnected = false;
+ break;
+ case PA_CONTEXT_FAILED:
+ impl->mConnected = false;
+ break;
+ default:;
+ }
+}
+
+/////////////////////////////////////////////////////
+
+VolumeCatcher::VolumeCatcher()
+{
+ pimpl = new VolumeCatcherImpl();
+}
+
+VolumeCatcher::~VolumeCatcher()
+{
+ delete pimpl;
+ pimpl = NULL;
+}
+
+void VolumeCatcher::setVolume(F32 volume)
+{
+ llassert(pimpl);
+ pimpl->setVolume(volume);
+}
+
+void VolumeCatcher::setPan(F32 pan)
+{
+ // TODO: implement this (if possible)
+}
+
+void VolumeCatcher::pump()
+{
+ llassert(pimpl);
+ pimpl->pump();
+}
diff --git a/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc b/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc
new file mode 100644
index 0000000000..d806b48428
--- /dev/null
+++ b/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc
@@ -0,0 +1,21 @@
+// required symbols to grab
+LL_PA_SYM(true, pa_context_connect, int, pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api);
+LL_PA_SYM(true, pa_context_disconnect, void, pa_context *c);
+LL_PA_SYM(true, pa_context_get_sink_input_info, pa_operation*, pa_context *c, uint32_t idx, pa_sink_input_info_cb_t cb, void *userdata);
+LL_PA_SYM(true, pa_context_get_sink_input_info_list, pa_operation*, pa_context *c, pa_sink_input_info_cb_t cb, void *userdata);
+LL_PA_SYM(true, pa_context_get_state, pa_context_state_t, pa_context *c);
+LL_PA_SYM(true, pa_context_new_with_proplist, pa_context*, pa_mainloop_api *mainloop, const char *name, pa_proplist *proplist);
+LL_PA_SYM(true, pa_context_set_sink_input_volume, pa_operation*, pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
+LL_PA_SYM(true, pa_context_set_state_callback, void, pa_context *c, pa_context_notify_cb_t cb, void *userdata);
+LL_PA_SYM(true, pa_context_set_subscribe_callback, void, pa_context *c, pa_context_subscribe_cb_t cb, void *userdata);
+LL_PA_SYM(true, pa_context_subscribe, pa_operation*, pa_context *c, pa_subscription_mask_t m, pa_context_success_cb_t cb, void *userdata);
+LL_PA_SYM(true, pa_context_unref, void, pa_context *c);
+LL_PA_SYM(true, pa_cvolume_set, pa_cvolume*, pa_cvolume *a, unsigned channels, pa_volume_t v);
+LL_PA_SYM(true, pa_operation_unref, void, pa_operation *o);
+LL_PA_SYM(true, pa_proplist_free, void, pa_proplist* p);
+LL_PA_SYM(true, pa_proplist_gets, const char*, pa_proplist *p, const char *key);
+LL_PA_SYM(true, pa_proplist_new, pa_proplist*, void);
+LL_PA_SYM(true, pa_proplist_sets, int, pa_proplist *p, const char *key, const char *value);
+LL_PA_SYM(true, pa_sw_volume_from_linear, pa_volume_t, double v);
+
+// optional symbols to grab
diff --git a/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc b/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc
new file mode 100644
index 0000000000..abf628c96c
--- /dev/null
+++ b/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc
@@ -0,0 +1,6 @@
+// required symbols to grab
+LL_PA_SYM(true, pa_glib_mainloop_free, void, pa_glib_mainloop* g);
+LL_PA_SYM(true, pa_glib_mainloop_get_api, pa_mainloop_api*, pa_glib_mainloop* g);
+LL_PA_SYM(true, pa_glib_mainloop_new, pa_glib_mainloop *, GMainContext *c);
+
+// optional symbols to grab
diff --git a/indra/media_plugins/webkit/mac_volume_catcher.cpp b/indra/media_plugins/webkit/mac_volume_catcher.cpp
new file mode 100644
index 0000000000..8a06bb8487
--- /dev/null
+++ b/indra/media_plugins/webkit/mac_volume_catcher.cpp
@@ -0,0 +1,268 @@
+/**
+ * @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.
+ *
+ * @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
+ */
+
+/**************************************************************************************************************
+ 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"
+
+#include <Carbon/Carbon.h>
+#include <QuickTime/QuickTime.h>
+#include <AudioUnit/AudioUnit.h>
+
+struct VolumeCatcherStorage;
+
+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();
+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;
+};
+
+VolumeCatcherImpl *VolumeCatcherImpl::sInstance = NULL;;
+
+struct VolumeCatcherStorage
+{
+ ComponentInstance self;
+ ComponentInstance delegate;
+};
+
+static ComponentResult volume_catcher_component_entry(ComponentParameters *cp, Handle componentStorage);
+static ComponentResult volume_catcher_component_open(VolumeCatcherStorage *storage, ComponentInstance self);
+static ComponentResult volume_catcher_component_close(VolumeCatcherStorage *storage, ComponentInstance self);
+
+VolumeCatcherImpl *VolumeCatcherImpl::getInstance()
+{
+ 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);
+
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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);
+ }
+}
+
+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...
+}
+
+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;
+ }
+}
+
+/////////////////////////////////////////////////////
+
+VolumeCatcher::VolumeCatcher()
+{
+ pimpl = VolumeCatcherImpl::getInstance();
+}
+
+VolumeCatcher::~VolumeCatcher()
+{
+ // Let the instance persist until exit.
+}
+
+void VolumeCatcher::setVolume(F32 volume)
+{
+ pimpl->setVolume(volume);
+}
+
+void VolumeCatcher::setPan(F32 pan)
+{
+ pimpl->setPan(pan);
+}
+
+void VolumeCatcher::pump()
+{
+ // No periodic tasks are necessary for this implementation.
+}
+
diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp
index 42d680ade6..047146f8f3 100644
--- a/indra/media_plugins/webkit/media_plugin_webkit.cpp
+++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp
@@ -3,30 +3,25 @@
* @brief Webkit plugin for LLMedia API plugin system
*
* @cond
- * $LicenseInfo:firstyear=2008&license=viewergpl$
- *
- * Copyright (c) 2008, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
*/
@@ -43,15 +38,28 @@
#include "llpluginmessageclasses.h"
#include "media_plugin_base.h"
+// set to 1 if you're using the version of llqtwebkit that's QPixmap-ified
+#if LL_LINUX
+# define LL_QTWEBKIT_USES_PIXMAPS 0
+extern "C" {
+# include <glib.h>
+# include <glib-object.h>
+}
+#else
+# define LL_QTWEBKIT_USES_PIXMAPS 0
+#endif // LL_LINUX
+
+# include "volume_catcher.h"
+
#if LL_WINDOWS
-#include <direct.h>
+# include <direct.h>
#else
-#include <unistd.h>
-#include <stdlib.h>
+# include <unistd.h>
+# include <stdlib.h>
#endif
#if LL_WINDOWS
- // *NOTE:Mani - This captures the module handle fo rthe dll. This is used below
+ // *NOTE:Mani - This captures the module handle for the dll. This is used below
// to get the path to this dll for webkit initialization.
// I don't know how/if this can be done with apr...
namespace { HMODULE gModuleHandle;};
@@ -77,10 +85,16 @@ public:
private:
std::string mProfileDir;
+ std::string mHostLanguage;
+ std::string mUserAgent;
+ bool mCookiesEnabled;
+ bool mJavascriptEnabled;
+ bool mPluginsEnabled;
enum
{
- INIT_STATE_UNINITIALIZED, // Browser instance hasn't been set up yet
+ INIT_STATE_UNINITIALIZED, // LLQtWebkit hasn't been set up yet
+ INIT_STATE_INITIALIZED, // LLQtWebkit has been set up, but no browser window has been created yet.
INIT_STATE_NAVIGATING, // Browser instance has been set up and initial navigate to about:blank has been issued
INIT_STATE_NAVIGATE_COMPLETE, // initial navigate to about:blank has completed
INIT_STATE_WAIT_REDRAW, // First real navigate begin has been received, waiting for page changed event to start handling redraws
@@ -102,6 +116,8 @@ private:
F32 mBackgroundG;
F32 mBackgroundB;
+ VolumeCatcher mVolumeCatcher;
+
void setInitState(int state)
{
// std::cerr << "changing init state to " << state << std::endl;
@@ -112,8 +128,20 @@ private:
//
void update(int milliseconds)
{
+#if LL_QTLINUX_DOESNT_HAVE_GLIB
+ // pump glib generously, as Linux browser plugins are on the
+ // glib main loop, even if the browser itself isn't - ugh
+ // This is NOT NEEDED if Qt itself was built with glib
+ // mainloop integration.
+ GMainContext *mainc = g_main_context_default();
+ while(g_main_context_iteration(mainc, FALSE));
+#endif // LL_QTLINUX_DOESNT_HAVE_GLIB
+
+ // pump qt
LLQtWebKit::getInstance()->pump( milliseconds );
+ mVolumeCatcher.pump();
+
checkEditState();
if(mInitState == INIT_STATE_NAVIGATE_COMPLETE)
@@ -130,7 +158,11 @@ private:
{
const unsigned char* browser_pixels = LLQtWebKit::getInstance()->grabBrowserWindow( mBrowserWindowId );
- unsigned int buffer_size = LLQtWebKit::getInstance()->getBrowserRowSpan( mBrowserWindowId ) * LLQtWebKit::getInstance()->getBrowserHeight( mBrowserWindowId );
+ unsigned int rowspan = LLQtWebKit::getInstance()->getBrowserRowSpan( mBrowserWindowId );
+ unsigned int height = LLQtWebKit::getInstance()->getBrowserHeight( mBrowserWindowId );
+#if !LL_QTWEBKIT_USES_PIXMAPS
+ unsigned int buffer_size = rowspan * height;
+#endif // !LL_QTWEBKIT_USES_PIXMAPS
// std::cerr << "webkit plugin: updating" << std::endl;
@@ -138,7 +170,16 @@ private:
if ( mPixels && browser_pixels )
{
// std::cerr << " memcopy of " << buffer_size << " bytes" << std::endl;
+
+#if LL_QTWEBKIT_USES_PIXMAPS
+ // copy the pixel data upside-down because of the co-ord system
+ for (int y=0; y<height; ++y)
+ {
+ memcpy( &mPixels[(height-y-1)*rowspan], &browser_pixels[y*rowspan], rowspan );
+ }
+#else
memcpy( mPixels, browser_pixels, buffer_size );
+#endif // LL_QTWEBKIT_USES_PIXMAPS
}
if ( mWidth > 0 && mHeight > 0 )
@@ -159,13 +200,6 @@ private:
if ( mInitState > INIT_STATE_UNINITIALIZED )
return true;
- // not enough information to initialize the browser yet.
- if ( mWidth < 0 || mHeight < 0 || mDepth < 0 ||
- mTextureWidth < 0 || mTextureHeight < 0 )
- {
- return false;
- };
-
// set up directories
char cwd[ FILENAME_MAX ]; // I *think* this is defined on all platforms we use
if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
@@ -175,13 +209,21 @@ private:
}
std::string application_dir = std::string( cwd );
+#if LL_LINUX
+ // take care to initialize glib properly, because some
+ // versions of Qt don't, and we indirectly need it for (some
+ // versions of) Flash to not crash the browser.
+ if (!g_thread_supported ()) g_thread_init (NULL);
+ g_type_init();
+#endif
+
#if LL_DARWIN
- // When running under the Xcode debugger, there's a setting called "Break on Debugger()/DebugStr()" which defaults to being turned on.
- // This causes the environment variable USERBREAK to be set to 1, which causes these legacy calls to break into the debugger.
- // This wouldn't cause any problems except for the fact that the current release version of the Flash plugin has a call to Debugger() in it
- // which gets hit when the plugin is probed by webkit.
- // Unsetting the environment variable here works around this issue.
- unsetenv("USERBREAK");
+ // When running under the Xcode debugger, there's a setting called "Break on Debugger()/DebugStr()" which defaults to being turned on.
+ // This causes the environment variable USERBREAK to be set to 1, which causes these legacy calls to break into the debugger.
+ // This wouldn't cause any problems except for the fact that the current release version of the Flash plugin has a call to Debugger() in it
+ // which gets hit when the plugin is probed by webkit.
+ // Unsetting the environment variable here works around this issue.
+ unsetenv("USERBREAK");
#endif
#if LL_WINDOWS
@@ -222,65 +264,94 @@ private:
bool result = LLQtWebKit::getInstance()->init( application_dir, component_dir, mProfileDir, native_window_handle );
if ( result )
{
- // create single browser window
- mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight );
-#if LL_WINDOWS
- // Enable plugins
- LLQtWebKit::getInstance()->enablePlugins(true);
-#elif LL_DARWIN
- // Enable plugins
- LLQtWebKit::getInstance()->enablePlugins(true);
-#elif LL_LINUX
- // Enable plugins
- LLQtWebKit::getInstance()->enablePlugins(true);
-#endif
- // Enable cookies
- LLQtWebKit::getInstance()->enableCookies( true );
-
- // tell LLQtWebKit about the size of the browser window
- LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight );
-
- // observer events that LLQtWebKit emits
- LLQtWebKit::getInstance()->addObserver( mBrowserWindowId, this );
-
- // append details to agent string
- LLQtWebKit::getInstance()->setBrowserAgentId( "LLPluginMedia Web Browser" );
-
- // don't flip bitmap
- LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true );
+ mInitState = INIT_STATE_INITIALIZED;
- // set background color
- // convert background color channels from [0.0, 1.0] to [0, 255];
- LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, int(mBackgroundR * 255.0f), int(mBackgroundG * 255.0f), int(mBackgroundB * 255.0f) );
-
- // Set state _before_ starting the navigate, since onNavigateBegin might get called before this call returns.
- setInitState(INIT_STATE_NAVIGATING);
-
- // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance.
- // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially
- // for the HTTP AUTH dialog issues (DEV-41731). Will fix at a later date.
- // Build a data URL like this: "data:text/html,%3Chtml%3E%3Cbody bgcolor=%22#RRGGBB%22%3E%3C/body%3E%3C/html%3E"
- // where RRGGBB is the background color in HTML style
- std::stringstream url;
-
- url << "data:text/html,%3Chtml%3E%3Cbody%20bgcolor=%22#";
- // convert background color channels from [0.0, 1.0] to [0, 255];
- url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundR * 255.0f);
- url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundG * 255.0f);
- url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundB * 255.0f);
- url << "%22%3E%3C/body%3E%3C/html%3E";
-
- lldebugs << "data url is: " << url.str() << llendl;
-
- LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, url.str() );
-// LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" );
-
return true;
};
return false;
};
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ bool initBrowserWindow()
+ {
+ // already initialized
+ if ( mInitState > INIT_STATE_INITIALIZED )
+ return true;
+
+ // not enough information to initialize the browser yet.
+ if ( mWidth < 0 || mHeight < 0 || mDepth < 0 ||
+ mTextureWidth < 0 || mTextureHeight < 0 )
+ {
+ return false;
+ };
+
+ // Set up host language before creating browser window
+ if(!mHostLanguage.empty())
+ {
+ LLQtWebKit::getInstance()->setHostLanguage(mHostLanguage);
+ }
+
+ // turn on/off cookies based on what host app tells us
+ LLQtWebKit::getInstance()->enableCookies( mCookiesEnabled );
+
+ // turn on/off plugins based on what host app tells us
+ LLQtWebKit::getInstance()->enablePlugins( mPluginsEnabled );
+
+ // turn on/off Javascript based on what host app tells us
+ LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled );
+
+ // create single browser window
+ mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight );
+
+ // tell LLQtWebKit about the size of the browser window
+ LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight );
+
+ // observer events that LLQtWebKit emits
+ LLQtWebKit::getInstance()->addObserver( mBrowserWindowId, this );
+
+ // append details to agent string
+ LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent );
+
+ // Set up window open behavior
+ LLQtWebKit::getInstance()->setWindowOpenBehavior(mBrowserWindowId, LLQtWebKit::WOB_SIMULATE_BLANK_HREF_CLICK);
+
+#if !LL_QTWEBKIT_USES_PIXMAPS
+ // don't flip bitmap
+ LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true );
+#endif // !LL_QTWEBKIT_USES_PIXMAPS
+
+ // set background color
+ // convert background color channels from [0.0, 1.0] to [0, 255];
+ LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, int(mBackgroundR * 255.0f), int(mBackgroundG * 255.0f), int(mBackgroundB * 255.0f) );
+
+ // Set state _before_ starting the navigate, since onNavigateBegin might get called before this call returns.
+ setInitState(INIT_STATE_NAVIGATING);
+
+ // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance.
+ // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially
+ // for the HTTP AUTH dialog issues (DEV-41731). Will fix at a later date.
+ // Build a data URL like this: "data:text/html,%3Chtml%3E%3Cbody bgcolor=%22#RRGGBB%22%3E%3C/body%3E%3C/html%3E"
+ // where RRGGBB is the background color in HTML style
+ std::stringstream url;
+
+ url << "data:text/html,%3Chtml%3E%3Cbody%20bgcolor=%22#";
+ // convert background color channels from [0.0, 1.0] to [0, 255];
+ url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundR * 255.0f);
+ url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundG * 255.0f);
+ url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundB * 255.0f);
+ url << "%22%3E%3C/body%3E%3C/html%3E";
+
+ lldebugs << "data url is: " << url.str() << llendl;
+
+ LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, url.str() );
+// LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" );
+
+ return true;
+ }
+
+ void setVolume(F32 vol);
////////////////////////////////////////////////////////////////////////////////
// virtual
@@ -451,6 +522,19 @@ private:
sendMessage(message);
}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onCookieChanged(const EventType& event)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "cookie_set");
+ message.setValue("cookie", event.getStringValue());
+ // These could be passed through as well, but aren't really needed.
+// message.setValue("uri", event.getEventUri());
+// message.setValueBoolean("dead", (event.getIntValue() != 0))
+ sendMessage(message);
+ }
+
LLQtWebKit::EKeyboardModifier decodeModifiers(std::string &modifiers)
{
int result = 0;
@@ -470,92 +554,96 @@ private:
return (LLQtWebKit::EKeyboardModifier)result;
}
-
////////////////////////////////////////////////////////////////////////////////
//
- void keyEvent(LLQtWebKit::EKeyEvent key_event, int key, LLQtWebKit::EKeyboardModifier modifiers)
+ void deserializeKeyboardData( LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers )
{
- int llqt_key;
+ native_scan_code = 0;
+ native_virtual_key = 0;
+ native_modifiers = 0;
+ if( native_key_data.isMap() )
+ {
+#if LL_DARWIN
+ native_scan_code = (uint32_t)(native_key_data["char_code"].asInteger());
+ native_virtual_key = (uint32_t)(native_key_data["key_code"].asInteger());
+ native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger());
+#elif LL_WINDOWS
+ native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger());
+ native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger());
+ // TODO: I don't think we need to do anything with native modifiers here -- please verify
+#elif LL_LINUX
+ native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger());
+ native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger());
+ native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger());
+#else
+ // Add other platforms here as needed
+#endif
+ };
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ void keyEvent(LLQtWebKit::EKeyEvent key_event, int key, LLQtWebKit::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap())
+ {
// The incoming values for 'key' will be the ones from indra_constants.h
- // the outgoing values are the ones from llqtwebkit.h
+ std::string utf8_text;
+
+ if(key < KEY_SPECIAL)
+ {
+ // Low-ascii characters need to get passed through.
+ utf8_text = (char)key;
+ }
+ // Any special-case handling we want to do for particular keys...
switch((KEY)key)
{
- // This is the list that the llqtwebkit implementation actually maps into Qt keys.
-// case KEY_XXX: llqt_key = LL_DOM_VK_CANCEL; break;
-// case KEY_XXX: llqt_key = LL_DOM_VK_HELP; break;
- case KEY_BACKSPACE: llqt_key = LL_DOM_VK_BACK_SPACE; break;
- case KEY_TAB: llqt_key = LL_DOM_VK_TAB; break;
-// case KEY_XXX: llqt_key = LL_DOM_VK_CLEAR; break;
- case KEY_RETURN: llqt_key = LL_DOM_VK_RETURN; break;
- case KEY_PAD_RETURN: llqt_key = LL_DOM_VK_ENTER; break;
- case KEY_SHIFT: llqt_key = LL_DOM_VK_SHIFT; break;
- case KEY_CONTROL: llqt_key = LL_DOM_VK_CONTROL; break;
- case KEY_ALT: llqt_key = LL_DOM_VK_ALT; break;
-// case KEY_XXX: llqt_key = LL_DOM_VK_PAUSE; break;
- case KEY_CAPSLOCK: llqt_key = LL_DOM_VK_CAPS_LOCK; break;
- case KEY_ESCAPE: llqt_key = LL_DOM_VK_ESCAPE; break;
- case KEY_PAGE_UP: llqt_key = LL_DOM_VK_PAGE_UP; break;
- case KEY_PAGE_DOWN: llqt_key = LL_DOM_VK_PAGE_DOWN; break;
- case KEY_END: llqt_key = LL_DOM_VK_END; break;
- case KEY_HOME: llqt_key = LL_DOM_VK_HOME; break;
- case KEY_LEFT: llqt_key = LL_DOM_VK_LEFT; break;
- case KEY_UP: llqt_key = LL_DOM_VK_UP; break;
- case KEY_RIGHT: llqt_key = LL_DOM_VK_RIGHT; break;
- case KEY_DOWN: llqt_key = LL_DOM_VK_DOWN; break;
-// case KEY_XXX: llqt_key = LL_DOM_VK_PRINTSCREEN; break;
- case KEY_INSERT: llqt_key = LL_DOM_VK_INSERT; break;
- case KEY_DELETE: llqt_key = LL_DOM_VK_DELETE; break;
-// case KEY_XXX: llqt_key = LL_DOM_VK_CONTEXT_MENU; break;
+ // ASCII codes for some standard keys
+ case LLQtWebKit::KEY_BACKSPACE: utf8_text = (char)8; break;
+ case LLQtWebKit::KEY_TAB: utf8_text = (char)9; break;
+ case LLQtWebKit::KEY_RETURN: utf8_text = (char)13; break;
+ case LLQtWebKit::KEY_PAD_RETURN: utf8_text = (char)13; break;
+ case LLQtWebKit::KEY_ESCAPE: utf8_text = (char)27; break;
- default:
- if(key < KEY_SPECIAL)
- {
- // Pass the incoming key through -- it should be regular ASCII, which should be correct for webkit.
- llqt_key = key;
- }
- else
- {
- // Don't pass through untranslated special keys -- they'll be all wrong.
- llqt_key = 0;
- }
+ default:
break;
}
-// std::cerr << "keypress, original code = 0x" << std::hex << key << ", converted code = 0x" << std::hex << llqt_key << std::dec << std::endl;
+// std::cerr << "key event " << (int)key_event << ", native_key_data = " << native_key_data << std::endl;
- if(llqt_key != 0)
- {
- LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, key_event, llqt_key, modifiers);
- }
+ uint32_t native_scan_code = 0;
+ uint32_t native_virtual_key = 0;
+ uint32_t native_modifiers = 0;
+ deserializeKeyboardData( native_key_data, native_scan_code, native_virtual_key, native_modifiers );
+
+ LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers);
checkEditState();
};
////////////////////////////////////////////////////////////////////////////////
//
- void unicodeInput( const std::string &utf8str, LLQtWebKit::EKeyboardModifier modifiers)
- {
- LLWString wstr = utf8str_to_wstring(utf8str);
+ void unicodeInput( const std::string &utf8str, LLQtWebKit::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap())
+ {
+ uint32_t key = LLQtWebKit::KEY_NONE;
+
+// std::cerr << "unicode input, native_key_data = " << native_key_data << std::endl;
- unsigned int i;
- for(i=0; i < wstr.size(); i++)
+ if(utf8str.size() == 1)
{
-// std::cerr << "unicode input, code = 0x" << std::hex << (unsigned long)(wstr[i]) << std::dec << std::endl;
-
- if(wstr[i] == 32)
- {
- // For some reason, the webkit plugin really wants the space bar to come in through the key-event path, not the unicode path.
- LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_DOWN, 32, modifiers);
- LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_UP, 32, modifiers);
- }
- else
- {
- LLQtWebKit::getInstance()->unicodeInput(mBrowserWindowId, wstr[i], modifiers);
- }
+ // The only way a utf8 string can be one byte long is if it's actually a single 7-bit ascii character.
+ // In this case, use it as the key value.
+ key = utf8str[0];
}
+ uint32_t native_scan_code = 0;
+ uint32_t native_virtual_key = 0;
+ uint32_t native_modifiers = 0;
+ deserializeKeyboardData( native_key_data, native_scan_code, native_virtual_key, native_modifiers );
+
+ LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_DOWN, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers);
+ LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_UP, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers);
+
checkEditState();
};
@@ -608,6 +696,14 @@ MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_
mLastMouseX = 0;
mLastMouseY = 0;
mFirstFocus = true;
+ mBackgroundR = 0.0f;
+ mBackgroundG = 0.0f;
+ mBackgroundB = 0.0f;
+
+ mHostLanguage = "en"; // default to english
+ mJavascriptEnabled = true; // default to on
+ mPluginsEnabled = true; // default to on
+ mUserAgent = "LLPluginMedia Web Browser";
}
MediaPluginWebKit::~MediaPluginWebKit()
@@ -634,9 +730,6 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
{
if(message_name == "init")
{
- std::string user_data_path = message_in.getValue("user_data_path"); // n.b. always has trailing platform-specific dir-delimiter
- mProfileDir = user_data_path + "browser_profile";
-
LLPluginMessage message("base", "init_response");
LLSD versions = LLSD::emptyMap();
versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
@@ -648,19 +741,6 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
plugin_version += LLQtWebKit::getInstance()->getVersion();
message.setValue("plugin_version", plugin_version);
sendMessage(message);
-
- // Plugin gets to decide the texture parameters to use.
- mDepth = 4;
-
- message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
- message.setValueS32("default_width", 1024);
- message.setValueS32("default_height", 1024);
- message.setValueS32("depth", mDepth);
- message.setValueU32("internalformat", GL_RGBA);
- message.setValueU32("format", GL_RGBA);
- message.setValueU32("type", GL_UNSIGNED_BYTE);
- message.setValueBoolean("coords_opengl", true);
- sendMessage(message);
}
else if(message_name == "idle")
{
@@ -725,9 +805,68 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
// std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl;
}
}
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+ {
+ if(message_name == "set_volume")
+ {
+ F32 volume = message_in.getValueReal("volume");
+ setVolume(volume);
+ }
+ }
else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
{
- if(message_name == "size_change")
+ if(message_name == "init")
+ {
+ // This is the media init message -- all necessary data for initialization should have been received.
+ if(initBrowser())
+ {
+
+ // Plugin gets to decide the texture parameters to use.
+ mDepth = 4;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
+ message.setValueS32("default_width", 1024);
+ message.setValueS32("default_height", 1024);
+ message.setValueS32("depth", mDepth);
+ message.setValueU32("internalformat", GL_RGBA);
+ #if LL_QTWEBKIT_USES_PIXMAPS
+ message.setValueU32("format", GL_BGRA_EXT); // I hope this isn't system-dependant... is it? If so, we'll have to check the root window's pixel layout or something... yuck.
+ #else
+ message.setValueU32("format", GL_RGBA);
+ #endif // LL_QTWEBKIT_USES_PIXMAPS
+ message.setValueU32("type", GL_UNSIGNED_BYTE);
+ message.setValueBoolean("coords_opengl", true);
+ sendMessage(message);
+ }
+ else
+ {
+ // if initialization failed, we're done.
+ mDeleteMe = true;
+ }
+
+ }
+ else if(message_name == "set_user_data_path")
+ {
+ std::string user_data_path = message_in.getValue("path"); // n.b. always has trailing platform-specific dir-delimiter
+ mProfileDir = user_data_path + "browser_profile";
+
+ // FIXME: Should we do anything with this if it comes in after the browser has been initialized?
+ }
+ else if(message_name == "set_language_code")
+ {
+ mHostLanguage = message_in.getValue("language");
+
+ // FIXME: Should we do anything with this if it comes in after the browser has been initialized?
+ }
+ else if(message_name == "plugins_enabled")
+ {
+ mPluginsEnabled = message_in.getValueBoolean("enable");
+ }
+ else if(message_name == "javascript_enabled")
+ {
+ mJavascriptEnabled = message_in.getValueBoolean("enable");
+ }
+ else if(message_name == "size_change")
{
std::string name = message_in.getValue("name");
S32 width = message_in.getValueS32("width");
@@ -749,29 +888,36 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
mWidth = width;
mHeight = height;
- // initialize (only gets called once)
- initBrowser();
-
- // size changed so tell the browser
- LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight );
-
-// std::cerr << "webkit plugin: set size to " << mWidth << " x " << mHeight
-// << ", rowspan is " << LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) << std::endl;
-
- S32 real_width = LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) / LLQtWebKit::getInstance()->getBrowserDepth(mBrowserWindowId);
-
- // The actual width the browser will be drawing to is probably smaller... let the host know by modifying texture_width in the response.
- if(real_width <= texture_width)
+ if(initBrowserWindow())
{
- texture_width = real_width;
+
+ // size changed so tell the browser
+ LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight );
+
+ // std::cerr << "webkit plugin: set size to " << mWidth << " x " << mHeight
+ // << ", rowspan is " << LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) << std::endl;
+
+ S32 real_width = LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) / LLQtWebKit::getInstance()->getBrowserDepth(mBrowserWindowId);
+
+ // The actual width the browser will be drawing to is probably smaller... let the host know by modifying texture_width in the response.
+ if(real_width <= texture_width)
+ {
+ texture_width = real_width;
+ }
+ else
+ {
+ // This won't work -- it'll be bigger than the allocated memory. This is a fatal error.
+ // std::cerr << "Fatal error: browser rowbytes greater than texture width" << std::endl;
+ mDeleteMe = true;
+ return;
+ }
}
else
{
- // This won't work -- it'll be bigger than the allocated memory. This is a fatal error.
-// std::cerr << "Fatal error: browser rowbytes greater than texture width" << std::endl;
+ // Setting up the browser window failed. This is a fatal error.
mDeleteMe = true;
- return;
}
+
mTextureWidth = texture_width;
mTextureHeight = texture_height;
@@ -852,6 +998,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
std::string event = message_in.getValue("event");
S32 key = message_in.getValueS32("key");
std::string modifiers = message_in.getValue("modifiers");
+ LLSD native_key_data = message_in.getValueLLSD("native_key_data");
// Treat unknown events as key-up for safety.
LLQtWebKit::EKeyEvent key_event = LLQtWebKit::KE_KEY_UP;
@@ -864,14 +1011,15 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
key_event = LLQtWebKit::KE_KEY_REPEAT;
}
- keyEvent(key_event, key, decodeModifiers(modifiers));
+ keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data);
}
else if(message_name == "text_event")
{
std::string text = message_in.getValue("text");
std::string modifiers = message_in.getValue("modifiers");
+ LLSD native_key_data = message_in.getValueLLSD("native_key_data");
- unicodeInput(text, decodeModifiers(modifiers));
+ unicodeInput(text, decodeModifiers(modifiers), native_key_data);
}
if(message_name == "edit_cut")
{
@@ -919,8 +1067,22 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
}
else if(message_name == "enable_cookies")
{
- bool val = message_in.getValueBoolean("enable");
- LLQtWebKit::getInstance()->enableCookies( val );
+ mCookiesEnabled = message_in.getValueBoolean("enable");
+ LLQtWebKit::getInstance()->enableCookies( mCookiesEnabled );
+ }
+ else if(message_name == "enable_plugins")
+ {
+ mPluginsEnabled = message_in.getValueBoolean("enable");
+ LLQtWebKit::getInstance()->enablePlugins( mPluginsEnabled );
+ }
+ else if(message_name == "enable_javascript")
+ {
+ mJavascriptEnabled = message_in.getValueBoolean("enable");
+ //LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled );
+ }
+ else if(message_name == "set_cookies")
+ {
+ LLQtWebKit::getInstance()->setCookies(message_in.getValue("cookies"));
}
else if(message_name == "proxy_setup")
{
@@ -957,8 +1119,8 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
}
else if(message_name == "set_user_agent")
{
- std::string user_agent = message_in.getValue("user_agent");
- LLQtWebKit::getInstance()->setBrowserAgentId( user_agent );
+ mUserAgent = message_in.getValue("user_agent");
+ LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent );
}
else if(message_name == "init_history")
{
@@ -989,6 +1151,11 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
}
}
+void MediaPluginWebKit::setVolume(F32 volume)
+{
+ mVolumeCatcher.setVolume(volume);
+}
+
int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
{
MediaPluginWebKit *self = new MediaPluginWebKit(host_send_func, host_user_data);
diff --git a/indra/media_plugins/webkit/volume_catcher.h b/indra/media_plugins/webkit/volume_catcher.h
new file mode 100644
index 0000000000..337f2913d3
--- /dev/null
+++ b/indra/media_plugins/webkit/volume_catcher.h
@@ -0,0 +1,54 @@
+/**
+ * @file volume_catcher.h
+ * @brief Interface to a class with platform-specific implementations that allows control of the audio volume of all sources in the current process.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#ifndef VOLUME_CATCHER_H
+#define VOLUME_CATCHER_H
+
+#include "linden_common.h"
+
+class VolumeCatcherImpl;
+
+class VolumeCatcher
+{
+ public:
+ VolumeCatcher();
+ ~VolumeCatcher();
+
+ void setVolume(F32 volume); // 0.0 - 1.0
+
+ // Set the left-right pan of audio sources
+ // where -1.0 = left, 0 = center, and 1.0 = right
+ void setPan(F32 pan);
+
+ void pump(); // call this at least a few times a second if you can - it affects how quickly we can 'catch' a new audio source and adjust its volume
+
+ private:
+ VolumeCatcherImpl *pimpl;
+};
+
+#endif // VOLUME_CATCHER_H
diff --git a/indra/media_plugins/webkit/windows_volume_catcher.cpp b/indra/media_plugins/webkit/windows_volume_catcher.cpp
new file mode 100644
index 0000000000..5fb84756ee
--- /dev/null
+++ b/indra/media_plugins/webkit/windows_volume_catcher.cpp
@@ -0,0 +1,117 @@
+/**
+ * @file windows_volume_catcher.cpp
+ * @brief A Windows implementation of volume level control of all audio channels opened by a process.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "volume_catcher.h"
+#include <windows.h>
+#include "llsingleton.h"
+class VolumeCatcherImpl : public LLSingleton<VolumeCatcherImpl>
+{
+friend LLSingleton<VolumeCatcherImpl>;
+public:
+
+ void setVolume(F32 volume);
+ void setPan(F32 pan);
+
+private:
+ // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance.
+ VolumeCatcherImpl();
+ ~VolumeCatcherImpl();
+
+ typedef void (WINAPI *set_volume_func_t)(F32);
+ typedef void (WINAPI *set_mute_func_t)(bool);
+
+ set_volume_func_t mSetVolumeFunc;
+ set_mute_func_t mSetMuteFunc;
+
+ F32 mVolume;
+ F32 mPan;
+};
+VolumeCatcherImpl::VolumeCatcherImpl()
+: mVolume(1.0f), // default volume is max
+ mPan(0.f) // default pan is centered
+{
+ HMODULE handle = ::LoadLibrary(L"winmm.dll");
+ if(handle)
+ {
+ mSetVolumeFunc = (set_volume_func_t)::GetProcAddress(handle, "setPluginVolume");
+ mSetMuteFunc = (set_mute_func_t)::GetProcAddress(handle, "setPluginMute");
+ }
+}
+
+VolumeCatcherImpl::~VolumeCatcherImpl()
+{
+}
+
+
+void VolumeCatcherImpl::setVolume(F32 volume)
+{
+ mVolume = volume;
+
+ if (mSetMuteFunc)
+ {
+ mSetMuteFunc(volume == 0.f);
+ }
+ if (mSetVolumeFunc)
+ {
+ mSetVolumeFunc(mVolume);
+ }
+}
+
+void VolumeCatcherImpl::setPan(F32 pan)
+{ // remember pan for calculating individual channel levels later
+ mPan = pan;
+}
+
+/////////////////////////////////////////////////////
+
+VolumeCatcher::VolumeCatcher()
+{
+ pimpl = VolumeCatcherImpl::getInstance();
+}
+
+VolumeCatcher::~VolumeCatcher()
+{
+ // Let the instance persist until exit.
+}
+
+void VolumeCatcher::setVolume(F32 volume)
+{
+ pimpl->setVolume(volume);
+}
+
+void VolumeCatcher::setPan(F32 pan)
+{
+ pimpl->setPan(pan);
+}
+
+void VolumeCatcher::pump()
+{
+ // No periodic tasks are necessary for this implementation.
+}
+
+
diff --git a/indra/media_plugins/winmmshim/CMakeLists.txt b/indra/media_plugins/winmmshim/CMakeLists.txt
new file mode 100644
index 0000000000..387214088f
--- /dev/null
+++ b/indra/media_plugins/winmmshim/CMakeLists.txt
@@ -0,0 +1,34 @@
+# -*- cmake -*-
+
+project(winmm_shim)
+
+### winmm_shim
+
+set(winmm_shim_SOURCE_FILES
+ forwarding_api.cpp
+ winmm_shim.cpp
+ )
+
+set(winmm_shim_HEADER_FILES
+ forwarding_api.h
+ winmm.def
+ )
+
+list(APPEND winmm_shim_SOURCE_FILES ${winmm_shim_HEADER_FILES})
+
+set_source_files_properties(${media_plugin_webkit_HEADER_FILES}
+ PROPERTIES HEADER_FILE_ONLY TRUE)
+
+add_library(winmm_shim
+ SHARED
+ ${winmm_shim_SOURCE_FILES}
+)
+
+if (WINDOWS)
+ set_target_properties(
+ winmm_shim
+ PROPERTIES
+ LINK_FLAGS "/MANIFEST:NO"
+ OUTPUT_NAME "winmm"
+ )
+endif (WINDOWS)
diff --git a/indra/media_plugins/winmmshim/forwarding_api.cpp b/indra/media_plugins/winmmshim/forwarding_api.cpp
new file mode 100644
index 0000000000..eff7e20451
--- /dev/null
+++ b/indra/media_plugins/winmmshim/forwarding_api.cpp
@@ -0,0 +1,1454 @@
+/**
+ * @file forwarding_api.cpp
+ * @brief forwards winmm API calls to real winmm.dll
+ *
+ * $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$
+ */
+
+#include "forwarding_api.h"
+
+CloseDriver_type CloseDriver_orig;
+OpenDriver_type OpenDriver_orig;
+SendDriverMessage_type SendDriverMessage_orig;
+DrvGetModuleHandle_type DrvGetModuleHandle_orig;
+GetDriverModuleHandle_type GetDriverModuleHandle_orig;
+DefDriverProc_type DefDriverProc_orig;
+DriverCallback_type DriverCallback_orig;
+mmsystemGetVersion_type mmsystemGetVersion_orig;
+sndPlaySoundA_type sndPlaySoundA_orig;
+sndPlaySoundW_type sndPlaySoundW_orig;
+PlaySoundA_type PlaySoundA_orig;
+PlaySoundW_type PlaySoundW_orig;
+waveOutGetNumDevs_type waveOutGetNumDevs_orig;
+waveOutGetDevCapsA_type waveOutGetDevCapsA_orig;
+waveOutGetDevCapsW_type waveOutGetDevCapsW_orig;
+waveOutGetVolume_type waveOutGetVolume_orig;
+waveOutSetVolume_type waveOutSetVolume_orig;
+waveOutGetErrorTextA_type waveOutGetErrorTextA_orig;
+waveOutGetErrorTextW_type waveOutGetErrorTextW_orig;
+waveOutOpen_type waveOutOpen_orig;
+waveOutClose_type waveOutClose_orig;
+waveOutPrepareHeader_type waveOutPrepareHeader_orig;
+waveOutUnprepareHeader_type waveOutUnprepareHeader_orig;
+waveOutWrite_type waveOutWrite_orig;
+waveOutPause_type waveOutPause_orig;
+waveOutRestart_type waveOutRestart_orig;
+waveOutReset_type waveOutReset_orig;
+waveOutBreakLoop_type waveOutBreakLoop_orig;
+waveOutGetPosition_type waveOutGetPosition_orig;
+waveOutGetPitch_type waveOutGetPitch_orig;
+waveOutSetPitch_type waveOutSetPitch_orig;
+waveOutGetPlaybackRate_type waveOutGetPlaybackRate_orig;
+waveOutSetPlaybackRate_type waveOutSetPlaybackRate_orig;
+waveOutGetID_type waveOutGetID_orig;
+waveOutMessage_type waveOutMessage_orig;
+waveInGetNumDevs_type waveInGetNumDevs_orig;
+waveInGetDevCapsA_type waveInGetDevCapsA_orig;
+waveInGetDevCapsW_type waveInGetDevCapsW_orig;
+waveInGetErrorTextA_type waveInGetErrorTextA_orig;
+waveInGetErrorTextW_type waveInGetErrorTextW_orig;
+waveInOpen_type waveInOpen_orig;
+waveInClose_type waveInClose_orig;
+waveInPrepareHeader_type waveInPrepareHeader_orig;
+waveInUnprepareHeader_type waveInUnprepareHeader_orig;
+waveInAddBuffer_type waveInAddBuffer_orig;
+waveInStart_type waveInStart_orig;
+waveInStop_type waveInStop_orig;
+waveInReset_type waveInReset_orig;
+waveInGetPosition_type waveInGetPosition_orig;
+waveInGetID_type waveInGetID_orig;
+waveInMessage_type waveInMessage_orig;
+midiOutGetNumDevs_type midiOutGetNumDevs_orig;
+midiStreamOpen_type midiStreamOpen_orig;
+midiStreamClose_type midiStreamClose_orig;
+midiStreamProperty_type midiStreamProperty_orig;
+midiStreamPosition_type midiStreamPosition_orig;
+midiStreamOut_type midiStreamOut_orig;
+midiStreamPause_type midiStreamPause_orig;
+midiStreamRestart_type midiStreamRestart_orig;
+midiStreamStop_type midiStreamStop_orig;
+midiConnect_type midiConnect_orig;
+midiDisconnect_type midiDisconnect_orig;
+midiOutGetDevCapsA_type midiOutGetDevCapsA_orig;
+midiOutGetDevCapsW_type midiOutGetDevCapsW_orig;
+midiOutGetVolume_type midiOutGetVolume_orig;
+midiOutSetVolume_type midiOutSetVolume_orig;
+midiOutGetErrorTextA_type midiOutGetErrorTextA_orig;
+midiOutGetErrorTextW_type midiOutGetErrorTextW_orig;
+midiOutOpen_type midiOutOpen_orig;
+midiOutClose_type midiOutClose_orig;
+midiOutPrepareHeader_type midiOutPrepareHeader_orig;
+midiOutUnprepareHeader_type midiOutUnprepareHeader_orig;
+midiOutShortMsg_type midiOutShortMsg_orig;
+midiOutLongMsg_type midiOutLongMsg_orig;
+midiOutReset_type midiOutReset_orig;
+midiOutCachePatches_type midiOutCachePatches_orig;
+midiOutCacheDrumPatches_type midiOutCacheDrumPatches_orig;
+midiOutGetID_type midiOutGetID_orig;
+midiOutMessage_type midiOutMessage_orig;
+midiInGetNumDevs_type midiInGetNumDevs_orig;
+midiInGetDevCapsA_type midiInGetDevCapsA_orig;
+midiInGetDevCapsW_type midiInGetDevCapsW_orig;
+midiInGetErrorTextA_type midiInGetErrorTextA_orig;
+midiInGetErrorTextW_type midiInGetErrorTextW_orig;
+midiInOpen_type midiInOpen_orig;
+midiInClose_type midiInClose_orig;
+midiInPrepareHeader_type midiInPrepareHeader_orig;
+midiInUnprepareHeader_type midiInUnprepareHeader_orig;
+midiInAddBuffer_type midiInAddBuffer_orig;
+midiInStart_type midiInStart_orig;
+midiInStop_type midiInStop_orig;
+midiInReset_type midiInReset_orig;
+midiInGetID_type midiInGetID_orig;
+midiInMessage_type midiInMessage_orig;
+auxGetNumDevs_type auxGetNumDevs_orig;
+auxGetDevCapsA_type auxGetDevCapsA_orig;
+auxGetDevCapsW_type auxGetDevCapsW_orig;
+auxSetVolume_type auxSetVolume_orig;
+auxGetVolume_type auxGetVolume_orig;
+auxOutMessage_type auxOutMessage_orig;
+mixerGetNumDevs_type mixerGetNumDevs_orig;
+mixerGetDevCapsA_type mixerGetDevCapsA_orig;
+mixerGetDevCapsW_type mixerGetDevCapsW_orig;
+mixerOpen_type mixerOpen_orig;
+mixerClose_type mixerClose_orig;
+mixerMessage_type mixerMessage_orig;
+mixerGetLineInfoA_type mixerGetLineInfoA_orig;
+mixerGetLineInfoW_type mixerGetLineInfoW_orig;
+mixerGetID_type mixerGetID_orig;
+mixerGetLineControlsA_type mixerGetLineControlsA_orig;
+mixerGetLineControlsW_type mixerGetLineControlsW_orig;
+mixerGetControlDetailsA_type mixerGetControlDetailsA_orig;
+mixerGetControlDetailsW_type mixerGetControlDetailsW_orig;
+mixerSetControlDetails_type mixerSetControlDetails_orig;
+mmGetCurrentTask_type mmGetCurrentTask_orig;
+mmTaskBlock_type mmTaskBlock_orig;
+mmTaskCreate_type mmTaskCreate_orig;
+mmTaskSignal_type mmTaskSignal_orig;
+mmTaskYield_type mmTaskYield_orig;
+timeGetSystemTime_type timeGetSystemTime_orig;
+timeGetTime_type timeGetTime_orig;
+timeSetEvent_type timeSetEvent_orig;
+timeKillEvent_type timeKillEvent_orig;
+timeGetDevCaps_type timeGetDevCaps_orig;
+timeBeginPeriod_type timeBeginPeriod_orig;
+timeEndPeriod_type timeEndPeriod_orig;
+joyGetNumDevs_type joyGetNumDevs_orig;
+joyConfigChanged_type joyConfigChanged_orig;
+joyGetDevCapsA_type joyGetDevCapsA_orig;
+joyGetDevCapsW_type joyGetDevCapsW_orig;
+joyGetPos_type joyGetPos_orig;
+joyGetPosEx_type joyGetPosEx_orig;
+joyGetThreshold_type joyGetThreshold_orig;
+joyReleaseCapture_type joyReleaseCapture_orig;
+joySetCapture_type joySetCapture_orig;
+joySetThreshold_type joySetThreshold_orig;
+mmioStringToFOURCCA_type mmioStringToFOURCCA_orig;
+mmioStringToFOURCCW_type mmioStringToFOURCCW_orig;
+mmioInstallIOProcA_type mmioInstallIOProcA_orig;
+mmioInstallIOProcW_type mmioInstallIOProcW_orig;
+mmioOpenA_type mmioOpenA_orig;
+mmioOpenW_type mmioOpenW_orig;
+mmioRenameA_type mmioRenameA_orig;
+mmioRenameW_type mmioRenameW_orig;
+mmioClose_type mmioClose_orig;
+mmioRead_type mmioRead_orig;
+mmioWrite_type mmioWrite_orig;
+mmioSeek_type mmioSeek_orig;
+mmioGetInfo_type mmioGetInfo_orig;
+mmioSetInfo_type mmioSetInfo_orig;
+mmioSetBuffer_type mmioSetBuffer_orig;
+mmioFlush_type mmioFlush_orig;
+mmioAdvance_type mmioAdvance_orig;
+mmioSendMessage_type mmioSendMessage_orig;
+mmioDescend_type mmioDescend_orig;
+mmioAscend_type mmioAscend_orig;
+mmioCreateChunk_type mmioCreateChunk_orig;
+mciSendCommandA_type mciSendCommandA_orig;
+mciSendCommandW_type mciSendCommandW_orig;
+mciSendStringA_type mciSendStringA_orig;
+mciSendStringW_type mciSendStringW_orig;
+mciGetDeviceIDA_type mciGetDeviceIDA_orig;
+mciGetDeviceIDW_type mciGetDeviceIDW_orig;
+mciGetDeviceIDFromElementIDA_type mciGetDeviceIDFromElementIDA_orig;
+mciGetDeviceIDFromElementIDW_type mciGetDeviceIDFromElementIDW_orig;
+mciGetDriverData_type mciGetDriverData_orig;
+mciGetErrorStringA_type mciGetErrorStringA_orig;
+mciGetErrorStringW_type mciGetErrorStringW_orig;
+mciSetDriverData_type mciSetDriverData_orig;
+mciDriverNotify_type mciDriverNotify_orig;
+mciDriverYield_type mciDriverYield_orig;
+mciSetYieldProc_type mciSetYieldProc_orig;
+mciFreeCommandResource_type mciFreeCommandResource_orig;
+mciGetCreatorTask_type mciGetCreatorTask_orig;
+mciGetYieldProc_type mciGetYieldProc_orig;
+mciLoadCommandResource_type mciLoadCommandResource_orig;
+mciExecute_type mciExecute_orig;
+
+// grab pointers to function calls in the real DLL
+void init_function_pointers(HMODULE winmm_handle)
+{
+ CloseDriver_orig = (CloseDriver_type)::GetProcAddress(winmm_handle, "CloseDriver");
+ OpenDriver_orig = (OpenDriver_type)::GetProcAddress(winmm_handle, "OpenDriver");
+ SendDriverMessage_orig = (SendDriverMessage_type)::GetProcAddress(winmm_handle, "SendDriverMessage");
+ DrvGetModuleHandle_orig = (DrvGetModuleHandle_type)::GetProcAddress(winmm_handle, "DrvGetModuleHandle");
+ GetDriverModuleHandle_orig = (GetDriverModuleHandle_type)::GetProcAddress(winmm_handle, "GetDriverModuleHandle");
+ DefDriverProc_orig = (DefDriverProc_type)::GetProcAddress(winmm_handle, "DefDriverProc");
+ DriverCallback_orig = (DriverCallback_type)::GetProcAddress(winmm_handle, "DriverCallback");
+ mmsystemGetVersion_orig = (mmsystemGetVersion_type)::GetProcAddress(winmm_handle, "mmsystemGetVersion");
+ sndPlaySoundA_orig = (sndPlaySoundA_type)::GetProcAddress(winmm_handle, "sndPlaySoundA");
+ sndPlaySoundW_orig = (sndPlaySoundW_type)::GetProcAddress(winmm_handle, "sndPlaySoundW");
+ PlaySoundA_orig = (PlaySoundA_type)::GetProcAddress(winmm_handle, "PlaySoundA");
+ PlaySoundW_orig = (PlaySoundW_type)::GetProcAddress(winmm_handle, "PlaySoundW");
+ waveOutGetNumDevs_orig = (waveOutGetNumDevs_type)::GetProcAddress(winmm_handle, "waveOutGetNumDevs");
+ waveOutGetDevCapsA_orig = (waveOutGetDevCapsA_type)::GetProcAddress(winmm_handle, "waveOutGetDevCapsA");
+ waveOutGetDevCapsW_orig = (waveOutGetDevCapsW_type)::GetProcAddress(winmm_handle, "waveOutGetDevCapsW");
+ waveOutGetVolume_orig = (waveOutGetVolume_type)::GetProcAddress(winmm_handle, "waveOutGetVolume");
+ waveOutSetVolume_orig = (waveOutSetVolume_type)::GetProcAddress(winmm_handle, "waveOutSetVolume");
+ waveOutGetErrorTextA_orig = (waveOutGetErrorTextA_type)::GetProcAddress(winmm_handle, "waveOutGetErrorTextA");
+ waveOutGetErrorTextW_orig = (waveOutGetErrorTextW_type)::GetProcAddress(winmm_handle, "waveOutGetErrorTextW");
+ waveOutOpen_orig = (waveOutOpen_type)::GetProcAddress(winmm_handle, "waveOutOpen");
+ waveOutClose_orig = (waveOutClose_type)::GetProcAddress(winmm_handle, "waveOutClose");
+ waveOutPrepareHeader_orig = (waveOutPrepareHeader_type)::GetProcAddress(winmm_handle, "waveOutPrepareHeader");
+ waveOutUnprepareHeader_orig = (waveOutUnprepareHeader_type)::GetProcAddress(winmm_handle, "waveOutUnprepareHeader");
+ waveOutWrite_orig = (waveOutWrite_type)::GetProcAddress(winmm_handle, "waveOutWrite");
+ waveOutPause_orig = (waveOutPause_type)::GetProcAddress(winmm_handle, "waveOutPause");
+ waveOutRestart_orig = (waveOutRestart_type)::GetProcAddress(winmm_handle, "waveOutRestart");
+ waveOutReset_orig = (waveOutReset_type)::GetProcAddress(winmm_handle, "waveOutReset");
+ waveOutBreakLoop_orig = (waveOutBreakLoop_type)::GetProcAddress(winmm_handle, "waveOutBreakLoop");
+ waveOutGetPosition_orig = (waveOutGetPosition_type)::GetProcAddress(winmm_handle, "waveOutGetPosition");
+ waveOutGetPitch_orig = (waveOutGetPitch_type)::GetProcAddress(winmm_handle, "waveOutGetPitch");
+ waveOutSetPitch_orig = (waveOutSetPitch_type)::GetProcAddress(winmm_handle, "waveOutSetPitch");
+ waveOutGetPlaybackRate_orig = (waveOutGetPlaybackRate_type)::GetProcAddress(winmm_handle, "waveOutGetPlaybackRate");
+ waveOutSetPlaybackRate_orig = (waveOutSetPlaybackRate_type)::GetProcAddress(winmm_handle, "waveOutSetPlaybackRate");
+ waveOutGetID_orig = (waveOutGetID_type)::GetProcAddress(winmm_handle, "waveOutGetID");
+ waveOutMessage_orig = (waveOutMessage_type)::GetProcAddress(winmm_handle, "waveOutMessage");
+ waveInGetNumDevs_orig = (waveInGetNumDevs_type)::GetProcAddress(winmm_handle, "waveInGetNumDevs");
+ waveInGetDevCapsA_orig = (waveInGetDevCapsA_type)::GetProcAddress(winmm_handle, "waveInGetDevCapsA");
+ waveInGetDevCapsW_orig = (waveInGetDevCapsW_type)::GetProcAddress(winmm_handle, "waveInGetDevCapsW");
+ waveInGetErrorTextA_orig = (waveInGetErrorTextA_type)::GetProcAddress(winmm_handle, "waveInGetErrorTextA");
+ waveInGetErrorTextW_orig = (waveInGetErrorTextW_type)::GetProcAddress(winmm_handle, "waveInGetErrorTextW");
+ waveInOpen_orig = (waveInOpen_type)::GetProcAddress(winmm_handle, "waveInOpen");
+ waveInClose_orig = (waveInClose_type)::GetProcAddress(winmm_handle, "waveInClose");
+ waveInPrepareHeader_orig = (waveInPrepareHeader_type)::GetProcAddress(winmm_handle, "waveInPrepareHeader");
+ waveInUnprepareHeader_orig = (waveInUnprepareHeader_type)::GetProcAddress(winmm_handle, "waveInUnprepareHeader");
+ waveInAddBuffer_orig = (waveInAddBuffer_type)::GetProcAddress(winmm_handle, "waveInAddBuffer");
+ waveInStart_orig = (waveInStart_type)::GetProcAddress(winmm_handle, "waveInStart");
+ waveInStop_orig = (waveInStop_type)::GetProcAddress(winmm_handle, "waveInStop");
+ waveInReset_orig = (waveInReset_type)::GetProcAddress(winmm_handle, "waveInReset");
+ waveInGetPosition_orig = (waveInGetPosition_type)::GetProcAddress(winmm_handle, "waveInGetPosition");
+ waveInGetID_orig = (waveInGetID_type)::GetProcAddress(winmm_handle, "waveInGetID");
+ waveInMessage_orig = (waveInMessage_type)::GetProcAddress(winmm_handle, "waveInMessage");
+ midiOutGetNumDevs_orig = (midiOutGetNumDevs_type)::GetProcAddress(winmm_handle, "midiOutGetNumDevs");
+ midiStreamOpen_orig = (midiStreamOpen_type)::GetProcAddress(winmm_handle, "midiStreamOpen");
+ midiStreamClose_orig = (midiStreamClose_type)::GetProcAddress(winmm_handle, "midiStreamClose");
+ midiStreamProperty_orig = (midiStreamProperty_type)::GetProcAddress(winmm_handle, "midiStreamProperty");
+ midiStreamPosition_orig = (midiStreamPosition_type)::GetProcAddress(winmm_handle, "midiStreamPosition");
+ midiStreamOut_orig = (midiStreamOut_type)::GetProcAddress(winmm_handle, "midiStreamOut");
+ midiStreamPause_orig = (midiStreamPause_type)::GetProcAddress(winmm_handle, "midiStreamPause");
+ midiStreamRestart_orig = (midiStreamRestart_type)::GetProcAddress(winmm_handle, "midiStreamRestart");
+ midiStreamStop_orig = (midiStreamStop_type)::GetProcAddress(winmm_handle, "midiStreamStop");
+ midiConnect_orig = (midiConnect_type)::GetProcAddress(winmm_handle, "midiConnect");
+ midiDisconnect_orig = (midiDisconnect_type)::GetProcAddress(winmm_handle, "midiDisconnect");
+ midiOutGetDevCapsA_orig = (midiOutGetDevCapsA_type)::GetProcAddress(winmm_handle, "midiOutGetDevCapsA");
+ midiOutGetDevCapsW_orig = (midiOutGetDevCapsW_type)::GetProcAddress(winmm_handle, "midiOutGetDevCapsW");
+ midiOutGetVolume_orig = (midiOutGetVolume_type)::GetProcAddress(winmm_handle, "midiOutGetVolume");
+ midiOutSetVolume_orig = (midiOutSetVolume_type)::GetProcAddress(winmm_handle, "midiOutSetVolume");
+ midiOutGetErrorTextA_orig = (midiOutGetErrorTextA_type)::GetProcAddress(winmm_handle, "midiOutGetErrorTextA");
+ midiOutGetErrorTextW_orig = (midiOutGetErrorTextW_type)::GetProcAddress(winmm_handle, "midiOutGetErrorTextW");
+ midiOutOpen_orig = (midiOutOpen_type)::GetProcAddress(winmm_handle, "midiOutOpen");
+ midiOutClose_orig = (midiOutClose_type)::GetProcAddress(winmm_handle, "midiOutClose");
+ midiOutPrepareHeader_orig = (midiOutPrepareHeader_type)::GetProcAddress(winmm_handle, "midiOutPrepareHeader");
+ midiOutUnprepareHeader_orig = (midiOutUnprepareHeader_type)::GetProcAddress(winmm_handle, "midiOutUnprepareHeader");
+ midiOutShortMsg_orig = (midiOutShortMsg_type)::GetProcAddress(winmm_handle, "midiOutShortMsg");
+ midiOutLongMsg_orig = (midiOutLongMsg_type)::GetProcAddress(winmm_handle, "midiOutLongMsg");
+ midiOutReset_orig = (midiOutReset_type)::GetProcAddress(winmm_handle, "midiOutReset");
+ midiOutCachePatches_orig = (midiOutCachePatches_type)::GetProcAddress(winmm_handle, "midiOutCachePatches");
+ midiOutCacheDrumPatches_orig = (midiOutCacheDrumPatches_type)::GetProcAddress(winmm_handle, "midiOutCacheDrumPatches");
+ midiOutGetID_orig = (midiOutGetID_type)::GetProcAddress(winmm_handle, "midiOutGetID");
+ midiOutMessage_orig = (midiOutMessage_type)::GetProcAddress(winmm_handle, "midiOutMessage");
+ midiInGetNumDevs_orig = (midiInGetNumDevs_type)::GetProcAddress(winmm_handle, "midiInGetNumDevs");
+ midiInGetDevCapsA_orig = (midiInGetDevCapsA_type)::GetProcAddress(winmm_handle, "midiInGetDevCapsA");
+ midiInGetDevCapsW_orig = (midiInGetDevCapsW_type)::GetProcAddress(winmm_handle, "midiInGetDevCapsW");
+ midiInGetErrorTextA_orig = (midiInGetErrorTextA_type)::GetProcAddress(winmm_handle, "midiInGetErrorTextA");
+ midiInGetErrorTextW_orig = (midiInGetErrorTextW_type)::GetProcAddress(winmm_handle, "midiInGetErrorTextW");
+ midiInOpen_orig = (midiInOpen_type)::GetProcAddress(winmm_handle, "midiInOpen");
+ midiInClose_orig = (midiInClose_type)::GetProcAddress(winmm_handle, "midiInClose");
+ midiInPrepareHeader_orig = (midiInPrepareHeader_type)::GetProcAddress(winmm_handle, "midiInPrepareHeader");
+ midiInUnprepareHeader_orig = (midiInUnprepareHeader_type)::GetProcAddress(winmm_handle, "midiInUnprepareHeader");
+ midiInAddBuffer_orig = (midiInAddBuffer_type)::GetProcAddress(winmm_handle, "midiInAddBuffer");
+ midiInStart_orig = (midiInStart_type)::GetProcAddress(winmm_handle, "midiInStart");
+ midiInStop_orig = (midiInStop_type)::GetProcAddress(winmm_handle, "midiInStop");
+ midiInReset_orig = (midiInReset_type)::GetProcAddress(winmm_handle, "midiInReset");
+ midiInGetID_orig = (midiInGetID_type)::GetProcAddress(winmm_handle, "midiInGetID");
+ midiInMessage_orig = (midiInMessage_type)::GetProcAddress(winmm_handle, "midiInMessage");
+ auxGetNumDevs_orig = (auxGetNumDevs_type)::GetProcAddress(winmm_handle, "auxGetNumDevs");
+ auxGetDevCapsA_orig = (auxGetDevCapsA_type)::GetProcAddress(winmm_handle, "auxGetDevCapsA");
+ auxGetDevCapsW_orig = (auxGetDevCapsW_type)::GetProcAddress(winmm_handle, "auxGetDevCapsW");
+ auxSetVolume_orig = (auxSetVolume_type)::GetProcAddress(winmm_handle, "auxSetVolume");
+ auxGetVolume_orig = (auxGetVolume_type)::GetProcAddress(winmm_handle, "auxGetVolume");
+ auxOutMessage_orig = (auxOutMessage_type)::GetProcAddress(winmm_handle, "auxOutMessage");
+ mixerGetNumDevs_orig = (mixerGetNumDevs_type)::GetProcAddress(winmm_handle, "mixerGetNumDevs");
+ mixerGetDevCapsA_orig = (mixerGetDevCapsA_type)::GetProcAddress(winmm_handle, "mixerGetDevCapsA");
+ mixerGetDevCapsW_orig = (mixerGetDevCapsW_type)::GetProcAddress(winmm_handle, "mixerGetDevCapsW");
+ mixerOpen_orig = (mixerOpen_type)::GetProcAddress(winmm_handle, "mixerOpen");
+ mixerClose_orig = (mixerClose_type)::GetProcAddress(winmm_handle, "mixerClose");
+ mixerMessage_orig = (mixerMessage_type)::GetProcAddress(winmm_handle, "mixerMessage");
+ mixerGetLineInfoA_orig = (mixerGetLineInfoA_type)::GetProcAddress(winmm_handle, "mixerGetLineInfoA");
+ mixerGetLineInfoW_orig = (mixerGetLineInfoW_type)::GetProcAddress(winmm_handle, "mixerGetLineInfoW");
+ mixerGetID_orig = (mixerGetID_type)::GetProcAddress(winmm_handle, "mixerGetID");
+ mixerGetLineControlsA_orig = (mixerGetLineControlsA_type)::GetProcAddress(winmm_handle, "mixerGetLineControlsA");
+ mixerGetLineControlsW_orig = (mixerGetLineControlsW_type)::GetProcAddress(winmm_handle, "mixerGetLineControlsW");
+ mixerGetControlDetailsA_orig = (mixerGetControlDetailsA_type)::GetProcAddress(winmm_handle, "mixerGetControlDetailsA");
+ mixerGetControlDetailsW_orig = (mixerGetControlDetailsW_type)::GetProcAddress(winmm_handle, "mixerGetControlDetailsW");
+ mixerSetControlDetails_orig = (mixerSetControlDetails_type)::GetProcAddress(winmm_handle, "mixerSetControlDetails");
+ mmGetCurrentTask_orig = (mmGetCurrentTask_type)::GetProcAddress(winmm_handle, "mmGetCurrentTask");
+ mmTaskBlock_orig = (mmTaskBlock_type)::GetProcAddress(winmm_handle, "mmTaskBlock");
+ mmTaskCreate_orig = (mmTaskCreate_type)::GetProcAddress(winmm_handle, "mmTaskCreate");
+ mmTaskSignal_orig = (mmTaskSignal_type)::GetProcAddress(winmm_handle, "mmTaskSignal");
+ mmTaskYield_orig = (mmTaskYield_type)::GetProcAddress(winmm_handle, "mmTaskYield");
+ timeGetSystemTime_orig = (timeGetSystemTime_type)::GetProcAddress(winmm_handle, "timeGetSystemTime");
+ timeGetTime_orig = (timeGetTime_type)::GetProcAddress(winmm_handle, "timeGetTime");
+ timeSetEvent_orig = (timeSetEvent_type)::GetProcAddress(winmm_handle, "timeSetEvent");
+ timeKillEvent_orig = (timeKillEvent_type)::GetProcAddress(winmm_handle, "timeKillEvent");
+ timeGetDevCaps_orig = (timeGetDevCaps_type)::GetProcAddress(winmm_handle, "timeGetDevCaps");
+ timeBeginPeriod_orig = (timeBeginPeriod_type)::GetProcAddress(winmm_handle, "timeBeginPeriod");
+ timeEndPeriod_orig = (timeEndPeriod_type)::GetProcAddress(winmm_handle, "timeEndPeriod");
+ joyGetNumDevs_orig = (joyGetNumDevs_type)::GetProcAddress(winmm_handle, "joyGetNumDevs");
+ joyConfigChanged_orig = (joyConfigChanged_type)::GetProcAddress(winmm_handle, "joyConfigChanged");
+ joyGetDevCapsA_orig = (joyGetDevCapsA_type)::GetProcAddress(winmm_handle, "joyGetDevCapsA");
+ joyGetDevCapsW_orig = (joyGetDevCapsW_type)::GetProcAddress(winmm_handle, "joyGetDevCapsW");
+ joyGetPos_orig = (joyGetPos_type)::GetProcAddress(winmm_handle, "joyGetPos");
+ joyGetPosEx_orig = (joyGetPosEx_type)::GetProcAddress(winmm_handle, "joyGetPosEx");
+ joyGetThreshold_orig = (joyGetThreshold_type)::GetProcAddress(winmm_handle, "joyGetThreshold");
+ joyReleaseCapture_orig = (joyReleaseCapture_type)::GetProcAddress(winmm_handle, "joyReleaseCapture");
+ joySetCapture_orig = (joySetCapture_type)::GetProcAddress(winmm_handle, "joySetCapture");
+ joySetThreshold_orig = (joySetThreshold_type)::GetProcAddress(winmm_handle, "joySetThreshold");
+ mciDriverNotify_orig = (mciDriverNotify_type)::GetProcAddress(winmm_handle, "mciDriverNotify");
+ mciDriverYield_orig = (mciDriverYield_type)::GetProcAddress(winmm_handle, "mciDriverYield");
+ mmioStringToFOURCCA_orig = (mmioStringToFOURCCA_type)::GetProcAddress(winmm_handle, "mmioStringToFOURCCA");
+ mmioStringToFOURCCW_orig = (mmioStringToFOURCCW_type)::GetProcAddress(winmm_handle, "mmioStringToFOURCCW");
+ mmioInstallIOProcA_orig = (mmioInstallIOProcA_type)::GetProcAddress(winmm_handle, "mmioInstallIOProcA");
+ mmioInstallIOProcW_orig = (mmioInstallIOProcW_type)::GetProcAddress(winmm_handle, "mmioInstallIOProcW");
+ mmioOpenA_orig = (mmioOpenA_type)::GetProcAddress(winmm_handle, "mmioOpenA");
+ mmioOpenW_orig = (mmioOpenW_type)::GetProcAddress(winmm_handle, "mmioOpenW");
+ mmioRenameA_orig = (mmioRenameA_type)::GetProcAddress(winmm_handle, "mmioRenameA");
+ mmioRenameW_orig = (mmioRenameW_type)::GetProcAddress(winmm_handle, "mmioRenameW");
+ mmioClose_orig = (mmioClose_type)::GetProcAddress(winmm_handle, "mmioClose");
+ mmioRead_orig = (mmioRead_type)::GetProcAddress(winmm_handle, "mmioRead");
+ mmioWrite_orig = (mmioWrite_type)::GetProcAddress(winmm_handle, "mmioWrite");
+ mmioSeek_orig = (mmioSeek_type)::GetProcAddress(winmm_handle, "mmioSeek");
+ mmioGetInfo_orig = (mmioGetInfo_type)::GetProcAddress(winmm_handle, "mmioGetInfo");
+ mmioSetInfo_orig = (mmioSetInfo_type)::GetProcAddress(winmm_handle, "mmioSetInfo");
+ mmioSetBuffer_orig = (mmioSetBuffer_type)::GetProcAddress(winmm_handle, "mmioSetBuffer");
+ mmioFlush_orig = (mmioFlush_type)::GetProcAddress(winmm_handle, "mmioFlush");
+ mmioAdvance_orig = (mmioAdvance_type)::GetProcAddress(winmm_handle, "mmioAdvance");
+ mmioSendMessage_orig = (mmioSendMessage_type)::GetProcAddress(winmm_handle, "mmioSendMessage");
+ mmioDescend_orig = (mmioDescend_type)::GetProcAddress(winmm_handle, "mmioDescend");
+ mmioAscend_orig = (mmioAscend_type)::GetProcAddress(winmm_handle, "mmioAscend");
+ mmioCreateChunk_orig = (mmioCreateChunk_type)::GetProcAddress(winmm_handle, "mmioCreateChunk");
+ mciSendCommandA_orig = (mciSendCommandA_type)::GetProcAddress(winmm_handle, "mciSendCommandA");
+ mciSendCommandW_orig = (mciSendCommandW_type)::GetProcAddress(winmm_handle, "mciSendCommandW");
+ mciSendStringA_orig = (mciSendStringA_type)::GetProcAddress(winmm_handle, "mciSendStringA");
+ mciSendStringW_orig = (mciSendStringW_type)::GetProcAddress(winmm_handle, "mciSendStringW");
+ mciGetDeviceIDA_orig = (mciGetDeviceIDA_type)::GetProcAddress(winmm_handle, "mciGetDeviceIDA");
+ mciGetDeviceIDW_orig = (mciGetDeviceIDW_type)::GetProcAddress(winmm_handle, "mciGetDeviceIDW");
+ mciGetDeviceIDFromElementIDA_orig = (mciGetDeviceIDFromElementIDA_type)::GetProcAddress(winmm_handle, "mciGetDeviceIDFromElementIDA");
+ mciGetDeviceIDFromElementIDW_orig = (mciGetDeviceIDFromElementIDW_type)::GetProcAddress(winmm_handle, "mciGetDeviceIDFromElementIDW");
+ mciGetDriverData_orig = (mciGetDriverData_type)::GetProcAddress(winmm_handle, "mciGetDriverData");
+ mciGetErrorStringA_orig = (mciGetErrorStringA_type)::GetProcAddress(winmm_handle, "mciGetErrorStringA");
+ mciGetErrorStringW_orig = (mciGetErrorStringW_type)::GetProcAddress(winmm_handle, "mciGetErrorStringW");
+ mciSetDriverData_orig = (mciSetDriverData_type)::GetProcAddress(winmm_handle, "mciSetDriverData");
+ mciSetYieldProc_orig = (mciSetYieldProc_type)::GetProcAddress(winmm_handle, "mciSetYieldProc");
+ mciFreeCommandResource_orig = (mciFreeCommandResource_type)::GetProcAddress(winmm_handle, "mciFreeCommandResource");
+ mciGetCreatorTask_orig = (mciGetCreatorTask_type)::GetProcAddress(winmm_handle, "mciGetCreatorTask");
+ mciGetYieldProc_orig = (mciGetYieldProc_type)::GetProcAddress(winmm_handle, "mciGetYieldProc");
+ mciLoadCommandResource_orig = (mciLoadCommandResource_type)::GetProcAddress(winmm_handle, "mciLoadCommandResource");
+ mciExecute_orig = (mciExecute_type)::GetProcAddress(winmm_handle, "mciExecute");
+}
+
+extern "C" {
+ LRESULT WINAPI CloseDriver( HDRVR hDriver, LPARAM lParam1, LPARAM lParam2)
+ {
+ //OutputDebugString(L"CloseDriver\n");
+ return CloseDriver_orig( hDriver, lParam1, lParam2);
+ }
+
+ HDRVR WINAPI OpenDriver( LPCWSTR szDriverName, LPCWSTR szSectionName, LPARAM lParam2)
+ {
+ //OutputDebugString(L"OpenDriver\n");
+ return OpenDriver_orig( szDriverName, szSectionName, lParam2);
+ }
+
+ LRESULT WINAPI SendDriverMessage( HDRVR hDriver, UINT message, LPARAM lParam1, LPARAM lParam2)
+ {
+ //OutputDebugString(L"SendDriverMessage\n");
+ return SendDriverMessage_orig( hDriver, message, lParam1, lParam2);
+ }
+
+ HMODULE WINAPI DrvGetModuleHandle( HDRVR hDriver)
+ {
+ //OutputDebugString(L"DrvGetModuleHandle\n");
+ return DrvGetModuleHandle_orig( hDriver);
+ }
+
+ HMODULE WINAPI GetDriverModuleHandle( HDRVR hDriver)
+ {
+ //OutputDebugString(L"GetDriverModuleHandle\n");
+ return GetDriverModuleHandle_orig( hDriver);
+ }
+
+ LRESULT WINAPI DefDriverProc( DWORD_PTR dwDriverIdentifier, HDRVR hdrvr, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
+ {
+ //OutputDebugString(L"DefDriverProc\n");
+ return DefDriverProc_orig( dwDriverIdentifier, hdrvr, uMsg, lParam1, lParam2);
+ }
+
+ BOOL WINAPI DriverCallback( DWORD dwCallBack, DWORD dwFlags, HDRVR hdrvr, DWORD msg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
+ {
+ //OutputDebugString(L"DriverCallback\n");
+ return DriverCallback_orig(dwCallBack, dwFlags, hdrvr, msg, dwUser, dwParam1, dwParam2);
+ }
+
+ UINT WINAPI mmsystemGetVersion(void)
+ {
+ //OutputDebugString(L"mmsystemGetVersion\n");
+ return mmsystemGetVersion_orig();
+ }
+
+ BOOL WINAPI sndPlaySoundA( LPCSTR pszSound, UINT fuSound)
+ {
+ //OutputDebugString(L"sndPlaySoundA\n");
+ return sndPlaySoundA_orig( pszSound, fuSound);
+ }
+
+ BOOL WINAPI sndPlaySoundW( LPCWSTR pszSound, UINT fuSound)
+ {
+ //OutputDebugString(L"sndPlaySoundW\n");
+ return sndPlaySoundW_orig( pszSound, fuSound);
+ }
+
+ BOOL WINAPI PlaySoundA( LPCSTR pszSound, HMODULE hmod, DWORD fdwSound)
+ {
+ //OutputDebugString(L"PlaySoundA\n");
+ return PlaySoundA_orig( pszSound, hmod, fdwSound);
+ }
+
+ BOOL WINAPI PlaySoundW( LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
+ {
+ //OutputDebugString(L"PlaySoundW\n");
+ return PlaySoundW_orig( pszSound, hmod, fdwSound);
+ }
+
+ UINT WINAPI waveOutGetNumDevs(void)
+ {
+ //OutputDebugString(L"waveOutGetNumDevs\n");
+ return waveOutGetNumDevs_orig();
+ }
+
+ MMRESULT WINAPI waveOutGetDevCapsA( UINT_PTR uDeviceID, LPWAVEOUTCAPSA pwoc, UINT cbwoc)
+ {
+ //OutputDebugString(L"waveOutGetDevCapsA\n");
+ return waveOutGetDevCapsA_orig( uDeviceID, pwoc, cbwoc);
+ }
+
+ MMRESULT WINAPI waveOutGetDevCapsW( UINT_PTR uDeviceID, LPWAVEOUTCAPSW pwoc, UINT cbwoc)
+ {
+ //OutputDebugString(L"waveOutGetDevCapsW\n");
+ return waveOutGetDevCapsW_orig( uDeviceID, pwoc, cbwoc);
+ }
+
+
+ MMRESULT WINAPI waveOutGetVolume( HWAVEOUT hwo, LPDWORD pdwVolume)
+ {
+ //OutputDebugString(L"waveOutGetVolume\n");
+ return waveOutGetVolume_orig( hwo, pdwVolume);
+ }
+
+ MMRESULT WINAPI waveOutSetVolume( HWAVEOUT hwo, DWORD dwVolume)
+ {
+ //OutputDebugString(L"waveOutSetVolume\n");
+ return waveOutSetVolume_orig( hwo, dwVolume);
+ }
+
+ MMRESULT WINAPI waveOutGetErrorTextA( MMRESULT mmrError, LPSTR pszText, UINT cchText)
+ {
+ //OutputDebugString(L"waveOutGetErrorTextA\n");
+ return waveOutGetErrorTextA_orig( mmrError, pszText, cchText);
+ }
+
+ MMRESULT WINAPI waveOutGetErrorTextW( MMRESULT mmrError, LPWSTR pszText, UINT cchText)
+ {
+ //OutputDebugString(L"waveOutGetErrorTextW\n");
+ return waveOutGetErrorTextW_orig( mmrError, pszText, cchText);
+ }
+
+ //MMRESULT WINAPI waveOutOpen( LPHWAVEOUT phwo, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen)
+ //{
+ // //OutputDebugString(L"waveOutGetErrorTextW\n");
+ // return waveOutOpen_orig( phwo, uDeviceID, pwfx, dwCallback, dwInstance, fdwOpen);
+ //}
+
+ //MMRESULT WINAPI waveOutClose( HWAVEOUT hwo)
+ //{
+ // //OutputDebugString(L"waveOutGetErrorTextW\n");
+ // return waveOutClose_orig( hwo );
+ //}
+
+ MMRESULT WINAPI waveOutPrepareHeader( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh)
+ {
+ //OutputDebugString(L"waveOutPrepareHeader\n");
+ return waveOutPrepareHeader_orig( hwo, pwh, cbwh);
+ }
+
+ MMRESULT WINAPI waveOutUnprepareHeader( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh)
+ {
+ //OutputDebugString(L"waveOutUnprepareHeader\n");
+ return waveOutUnprepareHeader_orig( hwo, pwh, cbwh);
+ }
+
+
+ //MMRESULT WINAPI waveOutWrite( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh)
+ //{
+ // //OutputDebugString(L"waveOutUnprepareHeader\n");
+ // return waveOutWrite_orig( hwo, pwh, cbwh);
+ //}
+
+ MMRESULT WINAPI waveOutPause( HWAVEOUT hwo)
+ {
+ //OutputDebugString(L"waveOutPause\n");
+ return waveOutPause_orig( hwo);
+ }
+
+ MMRESULT WINAPI waveOutRestart( HWAVEOUT hwo)
+ {
+ //OutputDebugString(L"waveOutRestart\n");
+ return waveOutRestart_orig( hwo);
+ }
+
+ MMRESULT WINAPI waveOutReset( HWAVEOUT hwo)
+ {
+ //OutputDebugString(L"waveOutReset\n");
+ return waveOutReset_orig( hwo);
+ }
+
+ MMRESULT WINAPI waveOutBreakLoop( HWAVEOUT hwo)
+ {
+ //OutputDebugString(L"waveOutBreakLoop\n");
+ return waveOutBreakLoop_orig( hwo);
+ }
+
+ MMRESULT WINAPI waveOutGetPosition( HWAVEOUT hwo, LPMMTIME pmmt, UINT cbmmt)
+ {
+ //OutputDebugString(L"waveOutGetPosition\n");
+ return waveOutGetPosition_orig( hwo, pmmt, cbmmt);
+ }
+
+ MMRESULT WINAPI waveOutGetPitch( HWAVEOUT hwo, LPDWORD pdwPitch)
+ {
+ //OutputDebugString(L"waveOutGetPitch\n");
+ return waveOutGetPitch_orig( hwo, pdwPitch);
+ }
+
+ MMRESULT WINAPI waveOutSetPitch( HWAVEOUT hwo, DWORD dwPitch)
+ {
+ //OutputDebugString(L"waveOutSetPitch\n");
+ return waveOutSetPitch_orig( hwo, dwPitch);
+ }
+
+ MMRESULT WINAPI waveOutGetPlaybackRate( HWAVEOUT hwo, LPDWORD pdwRate)
+ {
+ //OutputDebugString(L"waveOutGetPlaybackRate\n");
+ return waveOutGetPlaybackRate_orig( hwo, pdwRate);
+ }
+
+ MMRESULT WINAPI waveOutSetPlaybackRate( HWAVEOUT hwo, DWORD dwRate)
+ {
+ //OutputDebugString(L"waveOutSetPlaybackRate\n");
+ return waveOutSetPlaybackRate_orig( hwo, dwRate);
+ }
+
+ MMRESULT WINAPI waveOutGetID( HWAVEOUT hwo, LPUINT puDeviceID)
+ {
+ //OutputDebugString(L"waveOutGetID\n");
+ return waveOutGetID_orig( hwo, puDeviceID);
+ }
+
+ MMRESULT WINAPI waveOutMessage( HWAVEOUT hwo, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2)
+ {
+ //OutputDebugString(L"waveOutMessage\n");
+ return waveOutMessage_orig( hwo, uMsg, dw1, dw2);
+ }
+
+ UINT WINAPI waveInGetNumDevs(void)
+ {
+ //OutputDebugString(L"waveInGetNumDevs\n");
+ return waveInGetNumDevs_orig();
+ }
+
+ MMRESULT WINAPI waveInGetDevCapsA( UINT_PTR uDeviceID, LPWAVEINCAPSA pwic, UINT cbwic)
+ {
+ //OutputDebugString(L"waveInGetDevCapsA\n");
+ return waveInGetDevCapsA_orig( uDeviceID, pwic, cbwic);
+ }
+
+ MMRESULT WINAPI waveInGetDevCapsW( UINT_PTR uDeviceID, LPWAVEINCAPSW pwic, UINT cbwic)
+ {
+ //OutputDebugString(L"waveInGetDevCapsW\n");
+ return waveInGetDevCapsW_orig( uDeviceID, pwic, cbwic);
+ }
+
+ MMRESULT WINAPI waveInGetErrorTextA(MMRESULT mmrError, LPSTR pszText, UINT cchText)
+ {
+ //OutputDebugString(L"waveInGetErrorTextA\n");
+ return waveInGetErrorTextA_orig(mmrError, pszText, cchText);
+ }
+
+ MMRESULT WINAPI waveInGetErrorTextW(MMRESULT mmrError, LPWSTR pszText, UINT cchText)
+ {
+ //OutputDebugString(L"waveInGetErrorTextW\n");
+ return waveInGetErrorTextW_orig(mmrError, pszText, cchText);
+ }
+
+ MMRESULT WINAPI waveInOpen( LPHWAVEIN phwi, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen)
+ {
+ //OutputDebugString(L"waveInOpen\n");
+ return waveInOpen_orig(phwi, uDeviceID, pwfx, dwCallback, dwInstance, fdwOpen);
+ }
+
+ MMRESULT WINAPI waveInClose( HWAVEIN hwi)
+ {
+ //OutputDebugString(L"waveInClose\n");
+ return waveInClose_orig( hwi);
+ }
+
+ MMRESULT WINAPI waveInPrepareHeader( HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh)
+ {
+ //OutputDebugString(L"waveInPrepareHeader\n");
+ return waveInPrepareHeader_orig( hwi, pwh, cbwh);
+ }
+
+ MMRESULT WINAPI waveInUnprepareHeader( HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh)
+ {
+ //OutputDebugString(L"waveInUnprepareHeader\n");
+ return waveInUnprepareHeader_orig( hwi, pwh, cbwh);
+ }
+
+ MMRESULT WINAPI waveInAddBuffer( HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh)
+ {
+ //OutputDebugString(L"waveInAddBuffer\n");
+ return waveInAddBuffer_orig( hwi, pwh, cbwh);
+ }
+
+ MMRESULT WINAPI waveInStart( HWAVEIN hwi)
+ {
+ //OutputDebugString(L"waveInStart\n");
+ return waveInStart_orig( hwi);
+ }
+
+ MMRESULT WINAPI waveInStop( HWAVEIN hwi)
+ {
+ //OutputDebugString(L"waveInStop\n");
+ return waveInStop_orig(hwi);
+ }
+
+ MMRESULT WINAPI waveInReset( HWAVEIN hwi)
+ {
+ //OutputDebugString(L"waveInReset\n");
+ return waveInReset_orig(hwi);
+ }
+
+ MMRESULT WINAPI waveInGetPosition( HWAVEIN hwi, LPMMTIME pmmt, UINT cbmmt)
+ {
+ //OutputDebugString(L"waveInGetPosition\n");
+ return waveInGetPosition_orig( hwi, pmmt, cbmmt);
+ }
+
+ MMRESULT WINAPI waveInGetID( HWAVEIN hwi, LPUINT puDeviceID)
+ {
+ //OutputDebugString(L"waveInGetID\n");
+ return waveInGetID_orig( hwi, puDeviceID);
+ }
+
+ MMRESULT WINAPI waveInMessage( HWAVEIN hwi, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2)
+ {
+ //OutputDebugString(L"waveInMessage\n");
+ return waveInMessage_orig( hwi, uMsg, dw1, dw2);
+ }
+
+ UINT WINAPI midiOutGetNumDevs(void)
+ {
+ //OutputDebugString(L"midiOutGetNumDevs\n");
+ return midiOutGetNumDevs_orig();
+ }
+
+ MMRESULT WINAPI midiStreamOpen( LPHMIDISTRM phms, LPUINT puDeviceID, DWORD cMidi, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen)
+ {
+ //OutputDebugString(L"midiStreamOpen\n");
+ return midiStreamOpen_orig( phms, puDeviceID, cMidi, dwCallback, dwInstance, fdwOpen);
+ }
+
+ MMRESULT WINAPI midiStreamClose( HMIDISTRM hms)
+ {
+ //OutputDebugString(L"midiStreamClose\n");
+ return midiStreamClose_orig( hms);
+ }
+
+ MMRESULT WINAPI midiStreamProperty( HMIDISTRM hms, LPBYTE lppropdata, DWORD dwProperty)
+ {
+ //OutputDebugString(L"midiStreamProperty\n");
+ return midiStreamProperty_orig( hms, lppropdata, dwProperty);
+ }
+
+ MMRESULT WINAPI midiStreamPosition( HMIDISTRM hms, LPMMTIME lpmmt, UINT cbmmt)
+ {
+ //OutputDebugString(L"midiStreamPosition\n");
+ return midiStreamPosition_orig( hms, lpmmt, cbmmt);
+ }
+
+ MMRESULT WINAPI midiStreamOut( HMIDISTRM hms, LPMIDIHDR pmh, UINT cbmh)
+ {
+ //OutputDebugString(L"midiStreamOut\n");
+ return midiStreamOut_orig( hms, pmh, cbmh);
+ }
+
+ MMRESULT WINAPI midiStreamPause( HMIDISTRM hms)
+ {
+ //OutputDebugString(L"midiStreamPause\n");
+ return midiStreamPause_orig( hms);
+ }
+
+ MMRESULT WINAPI midiStreamRestart( HMIDISTRM hms)
+ {
+ //OutputDebugString(L"midiStreamRestart\n");
+ return midiStreamRestart_orig( hms);
+ }
+
+ MMRESULT WINAPI midiStreamStop( HMIDISTRM hms)
+ {
+ //OutputDebugString(L"midiStreamStop\n");
+ return midiStreamStop_orig( hms);
+ }
+
+ MMRESULT WINAPI midiConnect( HMIDI hmi, HMIDIOUT hmo, LPVOID pReserved)
+ {
+ //OutputDebugString(L"midiConnect\n");
+ return midiConnect_orig( hmi, hmo, pReserved);
+ }
+
+ MMRESULT WINAPI midiDisconnect( HMIDI hmi, HMIDIOUT hmo, LPVOID pReserved)
+ {
+ //OutputDebugString(L"midiDisconnect\n");
+ return midiDisconnect_orig( hmi, hmo, pReserved);
+ }
+
+ MMRESULT WINAPI midiOutGetDevCapsA( UINT_PTR uDeviceID, LPMIDIOUTCAPSA pmoc, UINT cbmoc)
+ {
+ //OutputDebugString(L"midiOutGetDevCapsA\n");
+ return midiOutGetDevCapsA_orig( uDeviceID, pmoc, cbmoc);
+ }
+
+ MMRESULT WINAPI midiOutGetDevCapsW( UINT_PTR uDeviceID, LPMIDIOUTCAPSW pmoc, UINT cbmoc)
+ {
+ //OutputDebugString(L"midiOutGetDevCapsW\n");
+ return midiOutGetDevCapsW_orig( uDeviceID, pmoc, cbmoc);
+ }
+
+ MMRESULT WINAPI midiOutGetVolume( HMIDIOUT hmo, LPDWORD pdwVolume)
+ {
+ //OutputDebugString(L"midiOutGetVolume\n");
+ return midiOutGetVolume_orig( hmo, pdwVolume);
+ }
+
+ MMRESULT WINAPI midiOutSetVolume( HMIDIOUT hmo, DWORD dwVolume)
+ {
+ //OutputDebugString(L"midiOutSetVolume\n");
+ return midiOutSetVolume_orig( hmo, dwVolume);
+ }
+
+ MMRESULT WINAPI midiOutGetErrorTextA( MMRESULT mmrError, LPSTR pszText, UINT cchText)
+ {
+ //OutputDebugString(L"midiOutGetErrorTextA\n");
+ return midiOutGetErrorTextA_orig( mmrError, pszText, cchText);
+ }
+
+ MMRESULT WINAPI midiOutGetErrorTextW( MMRESULT mmrError, LPWSTR pszText, UINT cchText)
+ {
+ //OutputDebugString(L"midiOutGetErrorTextW\n");
+ return midiOutGetErrorTextW_orig( mmrError, pszText, cchText);
+ }
+
+ MMRESULT WINAPI midiOutOpen( LPHMIDIOUT phmo, UINT uDeviceID, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen)
+ {
+ //OutputDebugString(L"midiOutOpen\n");
+ return midiOutOpen_orig(phmo, uDeviceID, dwCallback, dwInstance, fdwOpen);
+ }
+
+ MMRESULT WINAPI midiOutClose( HMIDIOUT hmo)
+ {
+ //OutputDebugString(L"midiOutClose\n");
+ return midiOutClose_orig( hmo);
+ }
+
+ MMRESULT WINAPI midiOutPrepareHeader( HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh)
+ {
+ //OutputDebugString(L"midiOutPrepareHeader\n");
+ return midiOutPrepareHeader_orig( hmo, pmh, cbmh);
+ }
+
+ MMRESULT WINAPI midiOutUnprepareHeader(HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh)
+ {
+ //OutputDebugString(L"midiOutUnprepareHeader\n");
+ return midiOutUnprepareHeader_orig(hmo, pmh, cbmh);
+ }
+
+ MMRESULT WINAPI midiOutShortMsg( HMIDIOUT hmo, DWORD dwMsg)
+ {
+ //OutputDebugString(L"midiOutShortMsg\n");
+ return midiOutShortMsg_orig( hmo, dwMsg);
+ }
+
+ MMRESULT WINAPI midiOutLongMsg(HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh)
+ {
+ //OutputDebugString(L"midiOutLongMsg\n");
+ return midiOutLongMsg_orig(hmo, pmh, cbmh);
+ }
+
+ MMRESULT WINAPI midiOutReset( HMIDIOUT hmo)
+ {
+ //OutputDebugString(L"midiOutReset\n");
+ return midiOutReset_orig( hmo);
+ }
+
+ MMRESULT WINAPI midiOutCachePatches( HMIDIOUT hmo, UINT uBank, LPWORD pwpa, UINT fuCache)
+ {
+ //OutputDebugString(L"midiOutCachePatches\n");
+ return midiOutCachePatches_orig( hmo, uBank, pwpa, fuCache);
+ }
+
+ MMRESULT WINAPI midiOutCacheDrumPatches( HMIDIOUT hmo, UINT uPatch, LPWORD pwkya, UINT fuCache)
+ {
+ //OutputDebugString(L"midiOutCacheDrumPatches\n");
+ return midiOutCacheDrumPatches_orig( hmo, uPatch, pwkya, fuCache);
+ }
+
+ MMRESULT WINAPI midiOutGetID( HMIDIOUT hmo, LPUINT puDeviceID)
+ {
+ //OutputDebugString(L"midiOutGetID\n");
+ return midiOutGetID_orig( hmo, puDeviceID);
+ }
+
+ MMRESULT WINAPI midiOutMessage( HMIDIOUT hmo, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2)
+ {
+ //OutputDebugString(L"midiOutMessage\n");
+ return midiOutMessage_orig( hmo, uMsg, dw1, dw2);
+ }
+
+ UINT WINAPI midiInGetNumDevs(void)
+ {
+ //OutputDebugString(L"midiInGetNumDevs\n");
+ return midiInGetNumDevs_orig();
+ }
+
+ MMRESULT WINAPI midiInGetDevCapsA( UINT_PTR uDeviceID, LPMIDIINCAPSA pmic, UINT cbmic)
+ {
+ //OutputDebugString(L"midiInGetDevCapsA\n");
+ return midiInGetDevCapsA_orig( uDeviceID, pmic, cbmic);
+ }
+
+ MMRESULT WINAPI midiInGetDevCapsW( UINT_PTR uDeviceID, LPMIDIINCAPSW pmic, UINT cbmic)
+ {
+ //OutputDebugString(L"midiInGetDevCapsW\n");
+ return midiInGetDevCapsW_orig( uDeviceID, pmic, cbmic);
+ }
+
+ MMRESULT WINAPI midiInGetErrorTextA( MMRESULT mmrError, LPSTR pszText, UINT cchText)
+ {
+ //OutputDebugString(L"midiInGetErrorTextA\n");
+ return midiInGetErrorTextA_orig( mmrError, pszText, cchText);
+ }
+
+ MMRESULT WINAPI midiInGetErrorTextW( MMRESULT mmrError, LPWSTR pszText, UINT cchText)
+ {
+ //OutputDebugString(L"midiInGetErrorTextW\n");
+ return midiInGetErrorTextW_orig( mmrError, pszText, cchText);
+ }
+
+ MMRESULT WINAPI midiInOpen( LPHMIDIIN phmi, UINT uDeviceID, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen)
+ {
+ //OutputDebugString(L"midiInOpen\n");
+ return midiInOpen_orig(phmi, uDeviceID, dwCallback, dwInstance, fdwOpen);
+ }
+
+ MMRESULT WINAPI midiInClose( HMIDIIN hmi)
+ {
+ //OutputDebugString(L"midiInClose\n");
+ return midiInClose_orig( hmi);
+ }
+
+ MMRESULT WINAPI midiInPrepareHeader( HMIDIIN hmi, LPMIDIHDR pmh, UINT cbmh)
+ {
+ //OutputDebugString(L"midiInPrepareHeader\n");
+ return midiInPrepareHeader_orig( hmi, pmh, cbmh);
+ }
+
+ MMRESULT WINAPI midiInUnprepareHeader( HMIDIIN hmi, LPMIDIHDR pmh, UINT cbmh)
+ {
+ //OutputDebugString(L"midiInUnprepareHeader\n");
+ return midiInUnprepareHeader_orig( hmi, pmh, cbmh);
+ }
+
+ MMRESULT WINAPI midiInAddBuffer( HMIDIIN hmi, LPMIDIHDR pmh, UINT cbmh)
+ {
+ //OutputDebugString(L"midiInAddBuffer\n");
+ return midiInAddBuffer_orig( hmi, pmh, cbmh);
+ }
+
+ MMRESULT WINAPI midiInStart( HMIDIIN hmi)
+ {
+ //OutputDebugString(L"midiInStart\n");
+ return midiInStart_orig( hmi);
+ }
+
+ MMRESULT WINAPI midiInStop( HMIDIIN hmi)
+ {
+ //OutputDebugString(L"midiInStop\n");
+ return midiInStop_orig(hmi);
+ }
+
+ MMRESULT WINAPI midiInReset( HMIDIIN hmi)
+ {
+ //OutputDebugString(L"midiInReset\n");
+ return midiInReset_orig( hmi);
+ }
+
+ MMRESULT WINAPI midiInGetID( HMIDIIN hmi, LPUINT puDeviceID)
+ {
+ //OutputDebugString(L"midiInGetID\n");
+ return midiInGetID_orig( hmi, puDeviceID);
+ }
+
+ MMRESULT WINAPI midiInMessage( HMIDIIN hmi, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2)
+ {
+ //OutputDebugString(L"midiInMessage\n");
+ return midiInMessage_orig( hmi, uMsg, dw1, dw2);
+ }
+
+ UINT WINAPI auxGetNumDevs(void)
+ {
+ //OutputDebugString(L"auxGetNumDevs\n");
+ return auxGetNumDevs_orig();
+ }
+
+ MMRESULT WINAPI auxGetDevCapsA( UINT_PTR uDeviceID, LPAUXCAPSA pac, UINT cbac)
+ {
+ //OutputDebugString(L"auxGetDevCapsA\n");
+ return auxGetDevCapsA_orig( uDeviceID, pac, cbac);
+ }
+
+ MMRESULT WINAPI auxGetDevCapsW( UINT_PTR uDeviceID, LPAUXCAPSW pac, UINT cbac)
+ {
+ //OutputDebugString(L"auxGetDevCapsW\n");
+ return auxGetDevCapsW_orig( uDeviceID, pac, cbac);
+ }
+
+ MMRESULT WINAPI auxSetVolume( UINT uDeviceID, DWORD dwVolume)
+ {
+ //OutputDebugString(L"auxSetVolume\n");
+ return auxSetVolume_orig( uDeviceID, dwVolume);
+ }
+
+ MMRESULT WINAPI auxGetVolume( UINT uDeviceID, LPDWORD pdwVolume)
+ {
+ //OutputDebugString(L"auxGetVolume\n");
+ return auxGetVolume_orig( uDeviceID, pdwVolume);
+ }
+
+ MMRESULT WINAPI auxOutMessage( UINT uDeviceID, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2)
+ {
+ //OutputDebugString(L"auxOutMessage\n");
+ return auxOutMessage_orig( uDeviceID, uMsg, dw1, dw2);
+ }
+
+ UINT WINAPI mixerGetNumDevs(void)
+ {
+ //OutputDebugString(L"mixerGetNumDevs\n");
+ return mixerGetNumDevs_orig();
+ }
+
+ MMRESULT WINAPI mixerGetDevCapsA( UINT_PTR uMxId, LPMIXERCAPSA pmxcaps, UINT cbmxcaps)
+ {
+ //OutputDebugString(L"mixerGetDevCapsA\n");
+ return mixerGetDevCapsA_orig( uMxId, pmxcaps, cbmxcaps);
+ }
+
+ MMRESULT WINAPI mixerGetDevCapsW( UINT_PTR uMxId, LPMIXERCAPSW pmxcaps, UINT cbmxcaps)
+ {
+ //OutputDebugString(L"mixerGetDevCapsW\n");
+ return mixerGetDevCapsW_orig( uMxId, pmxcaps, cbmxcaps);
+ }
+
+ MMRESULT WINAPI mixerOpen( LPHMIXER phmx, UINT uMxId, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen)
+ {
+ //OutputDebugString(L"mixerOpen\n");
+ return mixerOpen_orig( phmx, uMxId, dwCallback, dwInstance, fdwOpen);
+ }
+
+ MMRESULT WINAPI mixerClose( HMIXER hmx)
+ {
+ //OutputDebugString(L"mixerClose\n");
+ return mixerClose_orig( hmx);
+ }
+
+ DWORD WINAPI mixerMessage( HMIXER hmx, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
+ {
+ //OutputDebugString(L"mixerMessage\n");
+ return mixerMessage_orig( hmx, uMsg, dwParam1, dwParam2);
+ }
+
+ MMRESULT WINAPI mixerGetLineInfoA( HMIXEROBJ hmxobj, LPMIXERLINEA pmxl, DWORD fdwInfo)
+ {
+ //OutputDebugString(L"mixerGetLineInfoA\n");
+ return mixerGetLineInfoA_orig( hmxobj, pmxl, fdwInfo);
+ }
+
+ MMRESULT WINAPI mixerGetLineInfoW( HMIXEROBJ hmxobj, LPMIXERLINEW pmxl, DWORD fdwInfo)
+ {
+ //OutputDebugString(L"mixerGetLineInfoW\n");
+ return mixerGetLineInfoW_orig( hmxobj, pmxl, fdwInfo);
+ }
+
+ MMRESULT WINAPI mixerGetID( HMIXEROBJ hmxobj, UINT FAR *puMxId, DWORD fdwId)
+ {
+ //OutputDebugString(L"mixerGetID\n");
+ return mixerGetID_orig( hmxobj, puMxId, fdwId);
+ }
+
+ MMRESULT WINAPI mixerGetLineControlsA( HMIXEROBJ hmxobj, LPMIXERLINECONTROLSA pmxlc, DWORD fdwControls)
+ {
+ //OutputDebugString(L"mixerGetLineControlsA\n");
+ return mixerGetLineControlsA_orig( hmxobj, pmxlc, fdwControls);
+ }
+
+ MMRESULT WINAPI mixerGetLineControlsW( HMIXEROBJ hmxobj, LPMIXERLINECONTROLSW pmxlc, DWORD fdwControls)
+ {
+ //OutputDebugString(L"mixerGetLineControlsW\n");
+ return mixerGetLineControlsW_orig( hmxobj, pmxlc, fdwControls);
+ }
+
+ MMRESULT WINAPI mixerGetControlDetailsA( HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails)
+ {
+ //OutputDebugString(L"mixerGetControlDetailsA\n");
+ return mixerGetControlDetailsA_orig( hmxobj, pmxcd, fdwDetails);
+ }
+
+ MMRESULT WINAPI mixerGetControlDetailsW( HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails)
+ {
+ //OutputDebugString(L"mixerGetControlDetailsW\n");
+ return mixerGetControlDetailsW_orig( hmxobj, pmxcd, fdwDetails);
+ }
+
+ MMRESULT WINAPI mixerSetControlDetails( HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails)
+ {
+ //OutputDebugString(L"mixerSetControlDetails\n");
+ return mixerSetControlDetails_orig( hmxobj, pmxcd, fdwDetails);
+ }
+
+ DWORD WINAPI mmGetCurrentTask(void)
+ {
+ //OutputDebugString(L"mmGetCurrentTask\n");
+ return mmGetCurrentTask_orig();
+ }
+
+ void WINAPI mmTaskBlock(DWORD val)
+ {
+ //OutputDebugString(L"mmTaskBlock\n");
+ return mmTaskBlock_orig(val);
+ }
+
+ UINT WINAPI mmTaskCreate(LPTASKCALLBACK a, HANDLE* b, DWORD_PTR c)
+ {
+ //OutputDebugString(L"mmTaskCreate\n");
+ return mmTaskCreate_orig(a, b, c);
+ }
+
+ BOOL WINAPI mmTaskSignal(DWORD a)
+ {
+ //OutputDebugString(L"mmTaskSignal\n");
+ return mmTaskSignal_orig(a);
+ }
+
+ VOID WINAPI mmTaskYield()
+ {
+ //OutputDebugString(L"mmTaskYield\n");
+ mmTaskYield_orig();
+ }
+
+ MMRESULT WINAPI timeGetSystemTime( LPMMTIME pmmt, UINT cbmmt)
+ {
+ //OutputDebugString(L"timeGetSystemTime\n");
+ return timeGetSystemTime_orig( pmmt, cbmmt);
+ }
+
+ DWORD WINAPI timeGetTime(void)
+ {
+ //OutputDebugString(L"timeGetTime\n");
+ return timeGetTime_orig();
+ }
+
+ MMRESULT WINAPI timeSetEvent( UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_PTR dwUser, UINT fuEvent)
+ {
+ //OutputDebugString(L"timeSetEvent\n");
+ return timeSetEvent_orig(uDelay, uResolution, fptc, dwUser, fuEvent);
+ }
+
+ MMRESULT WINAPI timeKillEvent( UINT uTimerID)
+ {
+ //OutputDebugString(L"timeKillEvent\n");
+ return timeKillEvent_orig( uTimerID);
+ }
+
+ MMRESULT WINAPI timeGetDevCaps( LPTIMECAPS ptc, UINT cbtc)
+ {
+ //OutputDebugString(L"timeGetDevCaps\n");
+ return timeGetDevCaps_orig( ptc, cbtc);
+ }
+
+ MMRESULT WINAPI timeBeginPeriod( UINT uPeriod)
+ {
+ //OutputDebugString(L"timeBeginPeriod\n");
+ return timeBeginPeriod_orig( uPeriod);
+ }
+
+ MMRESULT WINAPI timeEndPeriod( UINT uPeriod)
+ {
+ //OutputDebugString(L"timeEndPeriod\n");
+ return timeEndPeriod_orig( uPeriod);
+ }
+
+ UINT WINAPI joyGetNumDevs(void)
+ {
+ //OutputDebugString(L"joyGetNumDevs\n");
+ return joyGetNumDevs_orig();
+ }
+
+ MMRESULT WINAPI joyConfigChanged(DWORD dwFlags)
+ {
+ //OutputDebugString(L"joyConfigChanged\n");
+ return joyConfigChanged_orig(dwFlags);
+ }
+
+ MMRESULT WINAPI joyGetDevCapsA( UINT_PTR uJoyID, LPJOYCAPSA pjc, UINT cbjc)
+ {
+ //OutputDebugString(L"joyGetDevCapsA\n");
+ return joyGetDevCapsA_orig( uJoyID, pjc, cbjc);
+ }
+
+ MMRESULT WINAPI joyGetDevCapsW( UINT_PTR uJoyID, LPJOYCAPSW pjc, UINT cbjc)
+ {
+ //OutputDebugString(L"joyGetDevCapsW\n");
+ return joyGetDevCapsW_orig( uJoyID, pjc, cbjc);
+ }
+
+ MMRESULT WINAPI joyGetPos( UINT uJoyID, LPJOYINFO pji)
+ {
+ //OutputDebugString(L"joyGetPos\n");
+ return joyGetPos_orig( uJoyID, pji);
+ }
+
+ MMRESULT WINAPI joyGetPosEx( UINT uJoyID, LPJOYINFOEX pji)
+ {
+ //OutputDebugString(L"joyGetPosEx\n");
+ return joyGetPosEx_orig( uJoyID, pji);
+ }
+
+ MMRESULT WINAPI joyGetThreshold( UINT uJoyID, LPUINT puThreshold)
+ {
+ //OutputDebugString(L"joyGetThreshold\n");
+ return joyGetThreshold_orig( uJoyID, puThreshold);
+ }
+
+ MMRESULT WINAPI joyReleaseCapture( UINT uJoyID)
+ {
+ //OutputDebugString(L"joyReleaseCapture\n");
+ return joyReleaseCapture_orig( uJoyID);
+ }
+
+ MMRESULT WINAPI joySetCapture( HWND hwnd, UINT uJoyID, UINT uPeriod, BOOL fChanged)
+ {
+ //OutputDebugString(L"joySetCapture\n");
+ return joySetCapture_orig(hwnd, uJoyID, uPeriod, fChanged);
+ }
+
+ MMRESULT WINAPI joySetThreshold( UINT uJoyID, UINT uThreshold)
+ {
+ //OutputDebugString(L"joySetThreshold\n");
+ return joySetThreshold_orig( uJoyID, uThreshold);
+ }
+
+ BOOL WINAPI mciDriverNotify(HWND hwndCallback, UINT uDeviceID, UINT uStatus)
+ {
+ //OutputDebugString(L"mciDriverNotify\n");
+ return mciDriverNotify_orig(hwndCallback, uDeviceID, uStatus);
+ }
+
+ UINT WINAPI mciDriverYield(UINT uDeviceID)
+ {
+ //OutputDebugString(L"mciDriverYield\n");
+ return mciDriverYield_orig(uDeviceID);
+ }
+
+ FOURCC WINAPI mmioStringToFOURCCA( LPCSTR sz, UINT uFlags)
+ {
+ //OutputDebugString(L"mmioStringToFOURCCA\n");
+ return mmioStringToFOURCCA_orig( sz, uFlags);
+ }
+
+ FOURCC WINAPI mmioStringToFOURCCW( LPCWSTR sz, UINT uFlags)
+ {
+ //OutputDebugString(L"mmioStringToFOURCCW\n");
+ return mmioStringToFOURCCW_orig( sz, uFlags);
+ }
+
+ LPMMIOPROC WINAPI mmioInstallIOProcA( FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags)
+ {
+ //OutputDebugString(L"mmioInstallIOProcA\n");
+ return mmioInstallIOProcA_orig( fccIOProc, pIOProc, dwFlags);
+ }
+
+ LPMMIOPROC WINAPI mmioInstallIOProcW( FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags)
+ {
+ //OutputDebugString(L"mmioInstallIOProcW\n");
+ return mmioInstallIOProcW_orig( fccIOProc, pIOProc, dwFlags);
+ }
+
+ HMMIO WINAPI mmioOpenA( LPSTR pszFileName, LPMMIOINFO pmmioinfo, DWORD fdwOpen)
+ {
+ //OutputDebugString(L"mmioOpenA\n");
+ return mmioOpenA_orig( pszFileName, pmmioinfo, fdwOpen);
+ }
+
+ HMMIO WINAPI mmioOpenW( LPWSTR pszFileName, LPMMIOINFO pmmioinfo, DWORD fdwOpen)
+ {
+ //OutputDebugString(L"mmioOpenW\n");
+ return mmioOpenW_orig( pszFileName, pmmioinfo, fdwOpen);
+ }
+
+ MMRESULT WINAPI mmioRenameA( LPCSTR pszFileName, LPCSTR pszNewFileName, LPCMMIOINFO pmmioinfo, DWORD fdwRename)
+ {
+ //OutputDebugString(L"mmioRenameA\n");
+ return mmioRenameA_orig( pszFileName, pszNewFileName, pmmioinfo, fdwRename);
+ }
+
+ MMRESULT WINAPI mmioRenameW( LPCWSTR pszFileName, LPCWSTR pszNewFileName, LPCMMIOINFO pmmioinfo, DWORD fdwRename)
+ {
+ //OutputDebugString(L"mmioRenameW\n");
+ return mmioRenameW_orig( pszFileName, pszNewFileName, pmmioinfo, fdwRename);
+ }
+
+ MMRESULT WINAPI mmioClose( HMMIO hmmio, UINT fuClose)
+ {
+ //OutputDebugString(L"mmioClose\n");
+ return mmioClose_orig( hmmio, fuClose);
+ }
+
+ LONG WINAPI mmioRead( HMMIO hmmio, HPSTR pch, LONG cch)
+ {
+ //OutputDebugString(L"mmioRead\n");
+ return mmioRead_orig( hmmio, pch, cch);
+ }
+
+ LONG WINAPI mmioWrite( HMMIO hmmio, const char _huge* pch, LONG cch)
+ {
+ //OutputDebugString(L"mmioWrite\n");
+ return mmioWrite_orig( hmmio, pch, cch);
+ }
+
+ LONG WINAPI mmioSeek( HMMIO hmmio, LONG lOffset, int iOrigin)
+ {
+ //OutputDebugString(L"mmioSeek\n");
+ return mmioSeek_orig(hmmio, lOffset, iOrigin);
+ }
+
+ MMRESULT WINAPI mmioGetInfo( HMMIO hmmio, LPMMIOINFO pmmioinfo, UINT fuInfo)
+ {
+ //OutputDebugString(L"mmioGetInfo\n");
+ return mmioGetInfo_orig( hmmio, pmmioinfo, fuInfo);
+ }
+
+ MMRESULT WINAPI mmioSetInfo( HMMIO hmmio, LPCMMIOINFO pmmioinfo, UINT fuInfo)
+ {
+ //OutputDebugString(L"mmioSetInfo\n");
+ return mmioSetInfo_orig( hmmio, pmmioinfo, fuInfo);
+ }
+
+ MMRESULT WINAPI mmioSetBuffer( HMMIO hmmio, LPSTR pchBuffer, LONG cchBuffer, UINT fuBuffer)
+ {
+ //OutputDebugString(L"mmioSetBuffer\n");
+ return mmioSetBuffer_orig(hmmio, pchBuffer, cchBuffer, fuBuffer);
+ }
+
+ MMRESULT WINAPI mmioFlush( HMMIO hmmio, UINT fuFlush)
+ {
+ //OutputDebugString(L"mmioFlush\n");
+ return mmioFlush_orig( hmmio, fuFlush);
+ }
+
+ MMRESULT WINAPI mmioAdvance( HMMIO hmmio, LPMMIOINFO pmmioinfo, UINT fuAdvance)
+ {
+ //OutputDebugString(L"mmioAdvance\n");
+ return mmioAdvance_orig( hmmio, pmmioinfo, fuAdvance);
+ }
+
+ LRESULT WINAPI mmioSendMessage( HMMIO hmmio, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
+ {
+ //OutputDebugString(L"mmioSendMessage\n");
+ return mmioSendMessage_orig(hmmio, uMsg, lParam1, lParam2);
+ }
+
+ MMRESULT WINAPI mmioDescend( HMMIO hmmio, LPMMCKINFO pmmcki, const MMCKINFO FAR* pmmckiParent, UINT fuDescend)
+ {
+ //OutputDebugString(L"mmioDescend\n");
+ return mmioDescend_orig(hmmio, pmmcki, pmmckiParent, fuDescend);
+ }
+
+ MMRESULT WINAPI mmioAscend( HMMIO hmmio, LPMMCKINFO pmmcki, UINT fuAscend)
+ {
+ //OutputDebugString(L"mmioAscend\n");
+ return mmioAscend_orig( hmmio, pmmcki, fuAscend);
+ }
+
+ MMRESULT WINAPI mmioCreateChunk(HMMIO hmmio, LPMMCKINFO pmmcki, UINT fuCreate)
+ {
+ //OutputDebugString(L"mmioCreateChunk\n");
+ return mmioCreateChunk_orig(hmmio, pmmcki, fuCreate);
+ }
+
+ MCIERROR WINAPI mciSendCommandA( MCIDEVICEID mciId, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
+ {
+ //OutputDebugString(L"mciSendCommandA\n");
+ return mciSendCommandA_orig( mciId, uMsg, dwParam1, dwParam2);
+ }
+
+ MCIERROR WINAPI mciSendCommandW( MCIDEVICEID mciId, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
+ {
+ //OutputDebugString(L"mciSendCommandW\n");
+ return mciSendCommandW_orig( mciId, uMsg, dwParam1, dwParam2);
+ }
+
+ MCIERROR WINAPI mciSendStringA( LPCSTR lpstrCommand, LPSTR lpstrReturnString, UINT uReturnLength, HWND hwndCallback)
+ {
+ //OutputDebugString(L"mciSendStringA\n");
+ return mciSendStringA_orig( lpstrCommand, lpstrReturnString, uReturnLength, hwndCallback);
+ }
+
+ MCIERROR WINAPI mciSendStringW( LPCWSTR lpstrCommand, LPWSTR lpstrReturnString, UINT uReturnLength, HWND hwndCallback)
+ {
+ //OutputDebugString(L"mciSendStringW\n");
+ return mciSendStringW_orig( lpstrCommand, lpstrReturnString, uReturnLength, hwndCallback);
+ }
+
+ MCIDEVICEID WINAPI mciGetDeviceIDA( LPCSTR pszDevice)
+ {
+ //OutputDebugString(L"mciGetDeviceIDA\n");
+ return mciGetDeviceIDA_orig( pszDevice);
+ }
+
+ MCIDEVICEID WINAPI mciGetDeviceIDW( LPCWSTR pszDevice)
+ {
+ //OutputDebugString(L"mciGetDeviceIDW\n");
+ return mciGetDeviceIDW_orig( pszDevice);
+ }
+
+ MCIDEVICEID WINAPI mciGetDeviceIDFromElementIDA( DWORD dwElementID, LPCSTR lpstrType )
+ {
+ //OutputDebugString(L"mciGetDeviceIDFromElementIDA\n");
+ return mciGetDeviceIDFromElementIDA_orig( dwElementID, lpstrType );
+ }
+
+ MCIDEVICEID WINAPI mciGetDeviceIDFromElementIDW( DWORD dwElementID, LPCWSTR lpstrType )
+ {
+ //OutputDebugString(L"mciGetDeviceIDFromElementIDW\n");
+ return mciGetDeviceIDFromElementIDW_orig( dwElementID, lpstrType );
+ }
+
+ DWORD_PTR WINAPI mciGetDriverData(UINT uDeviceID)
+ {
+ //OutputDebugString(L"mciGetDriverData\n");
+ return mciGetDriverData_orig(uDeviceID);
+ }
+
+ BOOL WINAPI mciGetErrorStringA( MCIERROR mcierr, LPSTR pszText, UINT cchText)
+ {
+ //OutputDebugString(L"mciGetErrorStringA\n");
+ return mciGetErrorStringA_orig( mcierr, pszText, cchText);
+ }
+
+ BOOL WINAPI mciGetErrorStringW( MCIERROR mcierr, LPWSTR pszText, UINT cchText)
+ {
+ //OutputDebugString(L"mciGetErrorStringW\n");
+ return mciGetErrorStringW_orig( mcierr, pszText, cchText);
+ }
+
+ BOOL WINAPI mciSetDriverData(UINT uDeviceID, DWORD_PTR dwData)
+ {
+ //OutputDebugString(L"mciSetDriverData_type\n");
+ return mciSetDriverData_orig( uDeviceID, dwData );
+ }
+
+ BOOL WINAPI mciSetYieldProc( MCIDEVICEID mciId, YIELDPROC fpYieldProc, DWORD dwYieldData)
+ {
+ //OutputDebugString(L"mciSetYieldProc\n");
+ return mciSetYieldProc_orig(mciId, fpYieldProc, dwYieldData);
+ }
+
+ BOOL WINAPI mciFreeCommandResource(UINT uTable)
+ {
+ //OutputDebugString(L"mciFreeCommandResource\n");
+ return mciFreeCommandResource_orig(uTable);
+ }
+
+ HTASK WINAPI mciGetCreatorTask( MCIDEVICEID mciId)
+ {
+ //OutputDebugString(L"mciGetCreatorTask\n");
+ return mciGetCreatorTask_orig( mciId);
+ }
+
+ YIELDPROC WINAPI mciGetYieldProc( MCIDEVICEID mciId, LPDWORD pdwYieldData)
+ {
+ //OutputDebugString(L"mciGetYieldProc\n");
+ return mciGetYieldProc_orig( mciId, pdwYieldData);
+ }
+
+ UINT WINAPI mciLoadCommandResource(HINSTANCE hInstance, LPCWSTR lpResName, UINT uType)
+ {
+ //OutputDebugString(L"mciLoadCommandResource");
+ return mciLoadCommandResource_orig(hInstance, lpResName, uType);
+ }
+
+
+ BOOL WINAPI mciExecute(LPCSTR pszCommand)
+ {
+ //OutputDebugString(L"mciExecute\n");
+ return mciExecute_orig(pszCommand);
+ }
+}
diff --git a/indra/media_plugins/winmmshim/forwarding_api.h b/indra/media_plugins/winmmshim/forwarding_api.h
new file mode 100644
index 0000000000..89a6b347f3
--- /dev/null
+++ b/indra/media_plugins/winmmshim/forwarding_api.h
@@ -0,0 +1,389 @@
+/**
+ * @file forwarding_api.h
+ * @brief forwards winmm API calls to real winmm.dll
+ *
+ * $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$
+ */
+
+// this turns off __declspec(dllimport) for the functions declared in mmsystem.h
+#define _WINMM_
+#include <windows.h>
+#include <mmsystem.h>
+
+void init_function_pointers(HMODULE winmm_handle);
+
+typedef VOID (*LPTASKCALLBACK)(DWORD_PTR dwInst);
+
+typedef LRESULT (WINAPI *CloseDriver_type)( HDRVR hDriver, LPARAM lParam1, LPARAM lParam2);
+extern CloseDriver_type CloseDriver_orig;
+typedef HDRVR (WINAPI *OpenDriver_type)( LPCWSTR szDriverName, LPCWSTR szSectionName, LPARAM lParam2);
+extern OpenDriver_type OpenDriver_orig;
+typedef LRESULT (WINAPI *SendDriverMessage_type)( HDRVR hDriver, UINT message, LPARAM lParam1, LPARAM lParam2);
+extern SendDriverMessage_type SendDriverMessage_orig;
+typedef HMODULE (WINAPI *DrvGetModuleHandle_type)( HDRVR hDriver);
+extern DrvGetModuleHandle_type DrvGetModuleHandle_orig;
+typedef HMODULE (WINAPI *GetDriverModuleHandle_type)( HDRVR hDriver);
+extern GetDriverModuleHandle_type GetDriverModuleHandle_orig;
+typedef LRESULT (WINAPI *DefDriverProc_type)( DWORD_PTR dwDriverIdentifier, HDRVR hdrvr, UINT uMsg, LPARAM lParam1, LPARAM lParam2);
+extern DefDriverProc_type DefDriverProc_orig;
+typedef BOOL (WINAPI *DriverCallback_type)(DWORD dwCallBack, DWORD dwFlags, HDRVR hdrvr, DWORD msg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2);
+extern DriverCallback_type DriverCallback_orig;
+typedef UINT (WINAPI *mmsystemGetVersion_type)(void);
+extern mmsystemGetVersion_type mmsystemGetVersion_orig;
+typedef BOOL (WINAPI *sndPlaySoundA_type)( LPCSTR pszSound, UINT fuSound);
+extern sndPlaySoundA_type sndPlaySoundA_orig;
+typedef BOOL (WINAPI *sndPlaySoundW_type)( LPCWSTR pszSound, UINT fuSound);
+extern sndPlaySoundW_type sndPlaySoundW_orig;
+typedef BOOL (WINAPI *PlaySoundA_type)( LPCSTR pszSound, HMODULE hmod, DWORD fdwSound);
+extern PlaySoundA_type PlaySoundA_orig;
+typedef BOOL (WINAPI *PlaySoundW_type)( LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound);
+extern PlaySoundW_type PlaySoundW_orig;
+typedef UINT (WINAPI *waveOutGetNumDevs_type)(void);
+extern waveOutGetNumDevs_type waveOutGetNumDevs_orig;
+typedef MMRESULT (WINAPI *waveOutGetDevCapsA_type)( UINT_PTR uDeviceID, LPWAVEOUTCAPSA pwoc, UINT cbwoc);
+extern waveOutGetDevCapsA_type waveOutGetDevCapsA_orig;
+typedef MMRESULT (WINAPI *waveOutGetDevCapsW_type)( UINT_PTR uDeviceID, LPWAVEOUTCAPSW pwoc, UINT cbwoc);
+extern waveOutGetDevCapsW_type waveOutGetDevCapsW_orig;
+typedef MMRESULT (WINAPI *waveOutGetVolume_type)( HWAVEOUT hwo, LPDWORD pdwVolume);
+extern waveOutGetVolume_type waveOutGetVolume_orig;
+typedef MMRESULT (WINAPI *waveOutSetVolume_type)( HWAVEOUT hwo, DWORD dwVolume);
+extern waveOutSetVolume_type waveOutSetVolume_orig;
+typedef MMRESULT (WINAPI *waveOutGetErrorTextA_type)( MMRESULT mmrError, LPSTR pszText, UINT cchText);
+extern waveOutGetErrorTextA_type waveOutGetErrorTextA_orig;
+typedef MMRESULT (WINAPI *waveOutGetErrorTextW_type)( MMRESULT mmrError, LPWSTR pszText, UINT cchText);
+extern waveOutGetErrorTextW_type waveOutGetErrorTextW_orig;
+typedef MMRESULT (WINAPI *waveOutOpen_type)( LPHWAVEOUT phwo, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen);
+extern waveOutOpen_type waveOutOpen_orig;
+typedef MMRESULT (WINAPI *waveOutClose_type)( HWAVEOUT hwo);
+extern waveOutClose_type waveOutClose_orig;
+typedef MMRESULT (WINAPI *waveOutPrepareHeader_type)( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
+extern waveOutPrepareHeader_type waveOutPrepareHeader_orig;
+typedef MMRESULT (WINAPI *waveOutUnprepareHeader_type)( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
+extern waveOutUnprepareHeader_type waveOutUnprepareHeader_orig;
+typedef MMRESULT (WINAPI *waveOutWrite_type)( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
+extern waveOutWrite_type waveOutWrite_orig;
+typedef MMRESULT (WINAPI *waveOutPause_type)( HWAVEOUT hwo);
+extern waveOutPause_type waveOutPause_orig;
+typedef MMRESULT (WINAPI *waveOutRestart_type)( HWAVEOUT hwo);
+extern waveOutRestart_type waveOutRestart_orig;
+typedef MMRESULT (WINAPI *waveOutReset_type)( HWAVEOUT hwo);
+extern waveOutReset_type waveOutReset_orig;
+typedef MMRESULT (WINAPI *waveOutBreakLoop_type)( HWAVEOUT hwo);
+extern waveOutBreakLoop_type waveOutBreakLoop_orig;
+typedef MMRESULT (WINAPI *waveOutGetPosition_type)( HWAVEOUT hwo, LPMMTIME pmmt, UINT cbmmt);
+extern waveOutGetPosition_type waveOutGetPosition_orig;
+typedef MMRESULT (WINAPI *waveOutGetPitch_type)( HWAVEOUT hwo, LPDWORD pdwPitch);
+extern waveOutGetPitch_type waveOutGetPitch_orig;
+typedef MMRESULT (WINAPI *waveOutSetPitch_type)( HWAVEOUT hwo, DWORD dwPitch);
+extern waveOutSetPitch_type waveOutSetPitch_orig;
+typedef MMRESULT (WINAPI *waveOutGetPlaybackRate_type)( HWAVEOUT hwo, LPDWORD pdwRate);
+extern waveOutGetPlaybackRate_type waveOutGetPlaybackRate_orig;
+typedef MMRESULT (WINAPI *waveOutSetPlaybackRate_type)( HWAVEOUT hwo, DWORD dwRate);
+extern waveOutSetPlaybackRate_type waveOutSetPlaybackRate_orig;
+typedef MMRESULT (WINAPI *waveOutGetID_type)( HWAVEOUT hwo, LPUINT puDeviceID);
+extern waveOutGetID_type waveOutGetID_orig;
+typedef MMRESULT (WINAPI *waveOutMessage_type)( HWAVEOUT hwo, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2);
+extern waveOutMessage_type waveOutMessage_orig;
+typedef UINT (WINAPI *waveInGetNumDevs_type)(void);
+extern waveInGetNumDevs_type waveInGetNumDevs_orig;
+typedef MMRESULT (WINAPI *waveInGetDevCapsA_type)( UINT_PTR uDeviceID, LPWAVEINCAPSA pwic, UINT cbwic);
+extern waveInGetDevCapsA_type waveInGetDevCapsA_orig;
+typedef MMRESULT (WINAPI *waveInGetDevCapsW_type)( UINT_PTR uDeviceID, LPWAVEINCAPSW pwic, UINT cbwic);
+extern waveInGetDevCapsW_type waveInGetDevCapsW_orig;
+typedef MMRESULT (WINAPI *waveInGetErrorTextA_type)(MMRESULT mmrError, LPSTR pszText, UINT cchText);
+extern waveInGetErrorTextA_type waveInGetErrorTextA_orig;
+typedef MMRESULT (WINAPI *waveInGetErrorTextW_type)(MMRESULT mmrError, LPWSTR pszText, UINT cchText);
+extern waveInGetErrorTextW_type waveInGetErrorTextW_orig;
+typedef MMRESULT (WINAPI *waveInOpen_type)( LPHWAVEIN phwi, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen);
+extern waveInOpen_type waveInOpen_orig;
+typedef MMRESULT (WINAPI *waveInClose_type)( HWAVEIN hwi);
+extern waveInClose_type waveInClose_orig;
+typedef MMRESULT (WINAPI *waveInPrepareHeader_type)( HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh);
+extern waveInPrepareHeader_type waveInPrepareHeader_orig;
+typedef MMRESULT (WINAPI *waveInUnprepareHeader_type)( HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh);
+extern waveInUnprepareHeader_type waveInUnprepareHeader_orig;
+typedef MMRESULT (WINAPI *waveInAddBuffer_type)( HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh);
+extern waveInAddBuffer_type waveInAddBuffer_orig;
+typedef MMRESULT (WINAPI *waveInStart_type)( HWAVEIN hwi);
+extern waveInStart_type waveInStart_orig;
+typedef MMRESULT (WINAPI *waveInStop_type)( HWAVEIN hwi);
+extern waveInStop_type waveInStop_orig;
+typedef MMRESULT (WINAPI *waveInReset_type)( HWAVEIN hwi);
+extern waveInReset_type waveInReset_orig;
+typedef MMRESULT (WINAPI *waveInGetPosition_type)( HWAVEIN hwi, LPMMTIME pmmt, UINT cbmmt);
+extern waveInGetPosition_type waveInGetPosition_orig;
+typedef MMRESULT (WINAPI *waveInGetID_type)( HWAVEIN hwi, LPUINT puDeviceID);
+extern waveInGetID_type waveInGetID_orig;
+typedef MMRESULT (WINAPI *waveInMessage_type)( HWAVEIN hwi, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2);
+extern waveInMessage_type waveInMessage_orig;
+typedef UINT (WINAPI *midiOutGetNumDevs_type)(void);
+extern midiOutGetNumDevs_type midiOutGetNumDevs_orig;
+typedef MMRESULT (WINAPI *midiStreamOpen_type)( LPHMIDISTRM phms, LPUINT puDeviceID, DWORD cMidi, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen);
+extern midiStreamOpen_type midiStreamOpen_orig;
+typedef MMRESULT (WINAPI *midiStreamClose_type)( HMIDISTRM hms);
+extern midiStreamClose_type midiStreamClose_orig;
+typedef MMRESULT (WINAPI *midiStreamProperty_type)( HMIDISTRM hms, LPBYTE lppropdata, DWORD dwProperty);
+extern midiStreamProperty_type midiStreamProperty_orig;
+typedef MMRESULT (WINAPI *midiStreamPosition_type)( HMIDISTRM hms, LPMMTIME lpmmt, UINT cbmmt);
+extern midiStreamPosition_type midiStreamPosition_orig;
+typedef MMRESULT (WINAPI *midiStreamOut_type)( HMIDISTRM hms, LPMIDIHDR pmh, UINT cbmh);
+extern midiStreamOut_type midiStreamOut_orig;
+typedef MMRESULT (WINAPI *midiStreamPause_type)( HMIDISTRM hms);
+extern midiStreamPause_type midiStreamPause_orig;
+typedef MMRESULT (WINAPI *midiStreamRestart_type)( HMIDISTRM hms);
+extern midiStreamRestart_type midiStreamRestart_orig;
+typedef MMRESULT (WINAPI *midiStreamStop_type)( HMIDISTRM hms);
+extern midiStreamStop_type midiStreamStop_orig;
+typedef MMRESULT (WINAPI *midiConnect_type)( HMIDI hmi, HMIDIOUT hmo, LPVOID pReserved);
+extern midiConnect_type midiConnect_orig;
+typedef MMRESULT (WINAPI *midiDisconnect_type)( HMIDI hmi, HMIDIOUT hmo, LPVOID pReserved);
+extern midiDisconnect_type midiDisconnect_orig;
+typedef MMRESULT (WINAPI *midiOutGetDevCapsA_type)( UINT_PTR uDeviceID, LPMIDIOUTCAPSA pmoc, UINT cbmoc);
+extern midiOutGetDevCapsA_type midiOutGetDevCapsA_orig;
+typedef MMRESULT (WINAPI *midiOutGetDevCapsW_type)( UINT_PTR uDeviceID, LPMIDIOUTCAPSW pmoc, UINT cbmoc);
+extern midiOutGetDevCapsW_type midiOutGetDevCapsW_orig;
+typedef MMRESULT (WINAPI *midiOutGetVolume_type)( HMIDIOUT hmo, LPDWORD pdwVolume);
+extern midiOutGetVolume_type midiOutGetVolume_orig;
+typedef MMRESULT (WINAPI *midiOutSetVolume_type)( HMIDIOUT hmo, DWORD dwVolume);
+extern midiOutSetVolume_type midiOutSetVolume_orig;
+typedef MMRESULT (WINAPI *midiOutGetErrorTextA_type)( MMRESULT mmrError, LPSTR pszText, UINT cchText);
+extern midiOutGetErrorTextA_type midiOutGetErrorTextA_orig;
+typedef MMRESULT (WINAPI *midiOutGetErrorTextW_type)( MMRESULT mmrError, LPWSTR pszText, UINT cchText);
+extern midiOutGetErrorTextW_type midiOutGetErrorTextW_orig;
+typedef MMRESULT (WINAPI *midiOutOpen_type)( LPHMIDIOUT phmo, UINT uDeviceID, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen);
+extern midiOutOpen_type midiOutOpen_orig;
+typedef MMRESULT (WINAPI *midiOutClose_type)( HMIDIOUT hmo);
+extern midiOutClose_type midiOutClose_orig;
+typedef MMRESULT (WINAPI *midiOutPrepareHeader_type)( HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh);
+extern midiOutPrepareHeader_type midiOutPrepareHeader_orig;
+typedef MMRESULT (WINAPI *midiOutUnprepareHeader_type)(HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh);
+extern midiOutUnprepareHeader_type midiOutUnprepareHeader_orig;
+typedef MMRESULT (WINAPI *midiOutShortMsg_type)( HMIDIOUT hmo, DWORD dwMsg);
+extern midiOutShortMsg_type midiOutShortMsg_orig;
+typedef MMRESULT (WINAPI *midiOutLongMsg_type)(HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh);
+extern midiOutLongMsg_type midiOutLongMsg_orig;
+typedef MMRESULT (WINAPI *midiOutReset_type)( HMIDIOUT hmo);
+extern midiOutReset_type midiOutReset_orig;
+typedef MMRESULT (WINAPI *midiOutCachePatches_type)( HMIDIOUT hmo, UINT uBank, LPWORD pwpa, UINT fuCache);
+extern midiOutCachePatches_type midiOutCachePatches_orig;
+typedef MMRESULT (WINAPI *midiOutCacheDrumPatches_type)( HMIDIOUT hmo, UINT uPatch, LPWORD pwkya, UINT fuCache);
+extern midiOutCacheDrumPatches_type midiOutCacheDrumPatches_orig;
+typedef MMRESULT (WINAPI *midiOutGetID_type)( HMIDIOUT hmo, LPUINT puDeviceID);
+extern midiOutGetID_type midiOutGetID_orig;
+typedef MMRESULT (WINAPI *midiOutMessage_type)( HMIDIOUT hmo, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2);
+extern midiOutMessage_type midiOutMessage_orig;
+typedef UINT (WINAPI *midiInGetNumDevs_type)(void);
+extern midiInGetNumDevs_type midiInGetNumDevs_orig;
+typedef MMRESULT (WINAPI *midiInGetDevCapsA_type)( UINT_PTR uDeviceID, LPMIDIINCAPSA pmic, UINT cbmic);
+extern midiInGetDevCapsA_type midiInGetDevCapsA_orig;
+typedef MMRESULT (WINAPI *midiInGetDevCapsW_type)( UINT_PTR uDeviceID, LPMIDIINCAPSW pmic, UINT cbmic);
+extern midiInGetDevCapsW_type midiInGetDevCapsW_orig;
+typedef MMRESULT (WINAPI *midiInGetErrorTextA_type)( MMRESULT mmrError, LPSTR pszText, UINT cchText);
+extern midiInGetErrorTextA_type midiInGetErrorTextA_orig;
+typedef MMRESULT (WINAPI *midiInGetErrorTextW_type)( MMRESULT mmrError, LPWSTR pszText, UINT cchText);
+extern midiInGetErrorTextW_type midiInGetErrorTextW_orig;
+typedef MMRESULT (WINAPI *midiInOpen_type)( LPHMIDIIN phmi, UINT uDeviceID, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen);
+extern midiInOpen_type midiInOpen_orig;
+typedef MMRESULT (WINAPI *midiInClose_type)( HMIDIIN hmi);
+extern midiInClose_type midiInClose_orig;
+typedef MMRESULT (WINAPI *midiInPrepareHeader_type)( HMIDIIN hmi, LPMIDIHDR pmh, UINT cbmh);
+extern midiInPrepareHeader_type midiInPrepareHeader_orig;
+typedef MMRESULT (WINAPI *midiInUnprepareHeader_type)( HMIDIIN hmi, LPMIDIHDR pmh, UINT cbmh);
+extern midiInUnprepareHeader_type midiInUnprepareHeader_orig;
+typedef MMRESULT (WINAPI *midiInAddBuffer_type)( HMIDIIN hmi, LPMIDIHDR pmh, UINT cbmh);
+extern midiInAddBuffer_type midiInAddBuffer_orig;
+typedef MMRESULT (WINAPI *midiInStart_type)( HMIDIIN hmi);
+extern midiInStart_type midiInStart_orig;
+typedef MMRESULT (WINAPI *midiInStop_type)( HMIDIIN hmi);
+extern midiInStop_type midiInStop_orig;
+typedef MMRESULT (WINAPI *midiInReset_type)( HMIDIIN hmi);
+extern midiInReset_type midiInReset_orig;
+typedef MMRESULT (WINAPI *midiInGetID_type)( HMIDIIN hmi, LPUINT puDeviceID);
+extern midiInGetID_type midiInGetID_orig;
+typedef MMRESULT (WINAPI *midiInMessage_type)( HMIDIIN hmi, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2);
+extern midiInMessage_type midiInMessage_orig;
+typedef UINT (WINAPI *auxGetNumDevs_type)(void);
+extern auxGetNumDevs_type auxGetNumDevs_orig;
+typedef MMRESULT (WINAPI *auxGetDevCapsA_type)( UINT_PTR uDeviceID, LPAUXCAPSA pac, UINT cbac);
+extern auxGetDevCapsA_type auxGetDevCapsA_orig;
+typedef MMRESULT (WINAPI *auxGetDevCapsW_type)( UINT_PTR uDeviceID, LPAUXCAPSW pac, UINT cbac);
+extern auxGetDevCapsW_type auxGetDevCapsW_orig;
+typedef MMRESULT (WINAPI *auxSetVolume_type)( UINT uDeviceID, DWORD dwVolume);
+extern auxSetVolume_type auxSetVolume_orig;
+typedef MMRESULT (WINAPI *auxGetVolume_type)( UINT uDeviceID, LPDWORD pdwVolume);
+extern auxGetVolume_type auxGetVolume_orig;
+typedef MMRESULT (WINAPI *auxOutMessage_type)( UINT uDeviceID, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2);
+extern auxOutMessage_type auxOutMessage_orig;
+typedef UINT (WINAPI *mixerGetNumDevs_type)(void);
+extern mixerGetNumDevs_type mixerGetNumDevs_orig;
+typedef MMRESULT (WINAPI *mixerGetDevCapsA_type)( UINT_PTR uMxId, LPMIXERCAPSA pmxcaps, UINT cbmxcaps);
+extern mixerGetDevCapsA_type mixerGetDevCapsA_orig;
+typedef MMRESULT (WINAPI *mixerGetDevCapsW_type)( UINT_PTR uMxId, LPMIXERCAPSW pmxcaps, UINT cbmxcaps);
+extern mixerGetDevCapsW_type mixerGetDevCapsW_orig;
+typedef MMRESULT (WINAPI *mixerOpen_type)( LPHMIXER phmx, UINT uMxId, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen);
+extern mixerOpen_type mixerOpen_orig;
+typedef MMRESULT (WINAPI *mixerClose_type)( HMIXER hmx);
+extern mixerClose_type mixerClose_orig;
+typedef DWORD (WINAPI *mixerMessage_type)( HMIXER hmx, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
+extern mixerMessage_type mixerMessage_orig;
+typedef MMRESULT (WINAPI *mixerGetLineInfoA_type)( HMIXEROBJ hmxobj, LPMIXERLINEA pmxl, DWORD fdwInfo);
+extern mixerGetLineInfoA_type mixerGetLineInfoA_orig;
+typedef MMRESULT (WINAPI *mixerGetLineInfoW_type)( HMIXEROBJ hmxobj, LPMIXERLINEW pmxl, DWORD fdwInfo);
+extern mixerGetLineInfoW_type mixerGetLineInfoW_orig;
+typedef MMRESULT (WINAPI *mixerGetID_type)( HMIXEROBJ hmxobj, UINT FAR *puMxId, DWORD fdwId);
+extern mixerGetID_type mixerGetID_orig;
+typedef MMRESULT (WINAPI *mixerGetLineControlsA_type)( HMIXEROBJ hmxobj, LPMIXERLINECONTROLSA pmxlc, DWORD fdwControls);
+extern mixerGetLineControlsA_type mixerGetLineControlsA_orig;
+typedef MMRESULT (WINAPI *mixerGetLineControlsW_type)( HMIXEROBJ hmxobj, LPMIXERLINECONTROLSW pmxlc, DWORD fdwControls);
+extern mixerGetLineControlsW_type mixerGetLineControlsW_orig;
+typedef MMRESULT (WINAPI *mixerGetControlDetailsA_type)( HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails);
+extern mixerGetControlDetailsA_type mixerGetControlDetailsA_orig;
+typedef MMRESULT (WINAPI *mixerGetControlDetailsW_type)( HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails);
+extern mixerGetControlDetailsW_type mixerGetControlDetailsW_orig;
+typedef MMRESULT (WINAPI *mixerSetControlDetails_type)( HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails);
+extern mixerSetControlDetails_type mixerSetControlDetails_orig;
+typedef DWORD (WINAPI *mmGetCurrentTask_type)(void);
+extern mmGetCurrentTask_type mmGetCurrentTask_orig;
+typedef void (WINAPI *mmTaskBlock_type)(DWORD);
+extern mmTaskBlock_type mmTaskBlock_orig;
+typedef UINT (WINAPI *mmTaskCreate_type)(LPTASKCALLBACK, HANDLE*, DWORD_PTR);
+extern mmTaskCreate_type mmTaskCreate_orig;
+typedef BOOL (WINAPI *mmTaskSignal_type)(DWORD);
+extern mmTaskSignal_type mmTaskSignal_orig;
+typedef VOID (WINAPI *mmTaskYield_type)(VOID);
+extern mmTaskYield_type mmTaskYield_orig;
+typedef MMRESULT (WINAPI *timeGetSystemTime_type)( LPMMTIME pmmt, UINT cbmmt);
+extern timeGetSystemTime_type timeGetSystemTime_orig;
+typedef DWORD (WINAPI *timeGetTime_type)(void);
+extern timeGetTime_type timeGetTime_orig;
+typedef MMRESULT (WINAPI *timeSetEvent_type)( UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_PTR dwUser, UINT fuEvent);
+extern timeSetEvent_type timeSetEvent_orig;
+typedef MMRESULT (WINAPI *timeKillEvent_type)( UINT uTimerID);
+extern timeKillEvent_type timeKillEvent_orig;
+typedef MMRESULT (WINAPI *timeGetDevCaps_type)( LPTIMECAPS ptc, UINT cbtc);
+extern timeGetDevCaps_type timeGetDevCaps_orig;
+typedef MMRESULT (WINAPI *timeBeginPeriod_type)( UINT uPeriod);
+extern timeBeginPeriod_type timeBeginPeriod_orig;
+typedef MMRESULT (WINAPI *timeEndPeriod_type)( UINT uPeriod);
+extern timeEndPeriod_type timeEndPeriod_orig;
+typedef UINT (WINAPI *joyGetNumDevs_type)(void);
+extern joyGetNumDevs_type joyGetNumDevs_orig;
+typedef MMRESULT (WINAPI *joyConfigChanged_type)(DWORD dwFlags);
+extern joyConfigChanged_type joyConfigChanged_orig;
+typedef MMRESULT (WINAPI *joyGetDevCapsA_type)( UINT_PTR uJoyID, LPJOYCAPSA pjc, UINT cbjc);
+extern joyGetDevCapsA_type joyGetDevCapsA_orig;
+typedef MMRESULT (WINAPI *joyGetDevCapsW_type)( UINT_PTR uJoyID, LPJOYCAPSW pjc, UINT cbjc);
+extern joyGetDevCapsW_type joyGetDevCapsW_orig;
+typedef MMRESULT (WINAPI *joyGetPos_type)( UINT uJoyID, LPJOYINFO pji);
+extern joyGetPos_type joyGetPos_orig;
+typedef MMRESULT (WINAPI *joyGetPosEx_type)( UINT uJoyID, LPJOYINFOEX pji);
+extern joyGetPosEx_type joyGetPosEx_orig;
+typedef MMRESULT (WINAPI *joyGetThreshold_type)( UINT uJoyID, LPUINT puThreshold);
+extern joyGetThreshold_type joyGetThreshold_orig;
+typedef MMRESULT (WINAPI *joyReleaseCapture_type)( UINT uJoyID);
+extern joyReleaseCapture_type joyReleaseCapture_orig;
+typedef MMRESULT (WINAPI *joySetCapture_type)( HWND hwnd, UINT uJoyID, UINT uPeriod, BOOL fChanged);
+extern joySetCapture_type joySetCapture_orig;
+typedef MMRESULT (WINAPI *joySetThreshold_type)( UINT uJoyID, UINT uThreshold);
+extern joySetThreshold_type joySetThreshold_orig;
+typedef BOOL (WINAPI *mciDriverNotify_type)(HWND hwndCallback, UINT uDeviceID, UINT uStatus);
+extern mciDriverNotify_type mciDriverNotify_orig;
+typedef UINT (WINAPI *mciDriverYield_type)(UINT uDeviceID);
+extern mciDriverYield_type mciDriverYield_orig;
+typedef FOURCC (WINAPI *mmioStringToFOURCCA_type)( LPCSTR sz, UINT uFlags);
+extern mmioStringToFOURCCA_type mmioStringToFOURCCA_orig;
+typedef FOURCC (WINAPI *mmioStringToFOURCCW_type)( LPCWSTR sz, UINT uFlags);
+extern mmioStringToFOURCCW_type mmioStringToFOURCCW_orig;
+typedef LPMMIOPROC (WINAPI *mmioInstallIOProcA_type)( FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags);
+extern mmioInstallIOProcA_type mmioInstallIOProcA_orig;
+typedef LPMMIOPROC (WINAPI *mmioInstallIOProcW_type)( FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags);
+extern mmioInstallIOProcW_type mmioInstallIOProcW_orig;
+typedef HMMIO (WINAPI *mmioOpenA_type)( LPSTR pszFileName, LPMMIOINFO pmmioinfo, DWORD fdwOpen);
+extern mmioOpenA_type mmioOpenA_orig;
+typedef HMMIO (WINAPI *mmioOpenW_type)( LPWSTR pszFileName, LPMMIOINFO pmmioinfo, DWORD fdwOpen);
+extern mmioOpenW_type mmioOpenW_orig;
+typedef MMRESULT (WINAPI *mmioRenameA_type)( LPCSTR pszFileName, LPCSTR pszNewFileName, LPCMMIOINFO pmmioinfo, DWORD fdwRename);
+extern mmioRenameA_type mmioRenameA_orig;
+typedef MMRESULT (WINAPI *mmioRenameW_type)( LPCWSTR pszFileName, LPCWSTR pszNewFileName, LPCMMIOINFO pmmioinfo, DWORD fdwRename);
+extern mmioRenameW_type mmioRenameW_orig;
+typedef MMRESULT (WINAPI *mmioClose_type)( HMMIO hmmio, UINT fuClose);
+extern mmioClose_type mmioClose_orig;
+typedef LONG (WINAPI *mmioRead_type)( HMMIO hmmio, HPSTR pch, LONG cch);
+extern mmioRead_type mmioRead_orig;
+typedef LONG (WINAPI *mmioWrite_type)( HMMIO hmmio, const char _huge* pch, LONG cch);
+extern mmioWrite_type mmioWrite_orig;
+typedef LONG (WINAPI *mmioSeek_type)( HMMIO hmmio, LONG lOffset, int iOrigin);
+extern mmioSeek_type mmioSeek_orig;
+typedef MMRESULT (WINAPI *mmioGetInfo_type)( HMMIO hmmio, LPMMIOINFO pmmioinfo, UINT fuInfo);
+extern mmioGetInfo_type mmioGetInfo_orig;
+typedef MMRESULT (WINAPI *mmioSetInfo_type)( HMMIO hmmio, LPCMMIOINFO pmmioinfo, UINT fuInfo);
+extern mmioSetInfo_type mmioSetInfo_orig;
+typedef MMRESULT (WINAPI *mmioSetBuffer_type)( HMMIO hmmio, LPSTR pchBuffer, LONG cchBuffer, UINT fuBuffer);
+extern mmioSetBuffer_type mmioSetBuffer_orig;
+typedef MMRESULT (WINAPI *mmioFlush_type)( HMMIO hmmio, UINT fuFlush);
+extern mmioFlush_type mmioFlush_orig;
+typedef MMRESULT (WINAPI *mmioAdvance_type)( HMMIO hmmio, LPMMIOINFO pmmioinfo, UINT fuAdvance);
+extern mmioAdvance_type mmioAdvance_orig;
+typedef LRESULT (WINAPI *mmioSendMessage_type)( HMMIO hmmio, UINT uMsg, LPARAM lParam1, LPARAM lParam2);
+extern mmioSendMessage_type mmioSendMessage_orig;
+typedef MMRESULT (WINAPI *mmioDescend_type)( HMMIO hmmio, LPMMCKINFO pmmcki, const MMCKINFO FAR* pmmckiParent, UINT fuDescend);
+extern mmioDescend_type mmioDescend_orig;
+typedef MMRESULT (WINAPI *mmioAscend_type)( HMMIO hmmio, LPMMCKINFO pmmcki, UINT fuAscend);
+extern mmioAscend_type mmioAscend_orig;
+typedef MMRESULT (WINAPI *mmioCreateChunk_type)(HMMIO hmmio, LPMMCKINFO pmmcki, UINT fuCreate);
+extern mmioCreateChunk_type mmioCreateChunk_orig;
+typedef MCIERROR (WINAPI *mciSendCommandA_type)( MCIDEVICEID mciId, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
+extern mciSendCommandA_type mciSendCommandA_orig;
+typedef MCIERROR (WINAPI *mciSendCommandW_type)( MCIDEVICEID mciId, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
+extern mciSendCommandW_type mciSendCommandW_orig;
+typedef MCIERROR (WINAPI *mciSendStringA_type)( LPCSTR lpstrCommand, LPSTR lpstrReturnString, UINT uReturnLength, HWND hwndCallback);
+extern mciSendStringA_type mciSendStringA_orig;
+typedef MCIERROR (WINAPI *mciSendStringW_type)( LPCWSTR lpstrCommand, LPWSTR lpstrReturnString, UINT uReturnLength, HWND hwndCallback);
+extern mciSendStringW_type mciSendStringW_orig;
+typedef MCIDEVICEID (WINAPI *mciGetDeviceIDA_type)( LPCSTR pszDevice);
+extern mciGetDeviceIDA_type mciGetDeviceIDA_orig;
+typedef MCIDEVICEID (WINAPI *mciGetDeviceIDW_type)( LPCWSTR pszDevice);
+extern mciGetDeviceIDW_type mciGetDeviceIDW_orig;
+typedef MCIDEVICEID (WINAPI *mciGetDeviceIDFromElementIDA_type)( DWORD dwElementID, LPCSTR lpstrType );
+extern mciGetDeviceIDFromElementIDA_type mciGetDeviceIDFromElementIDA_orig;
+typedef MCIDEVICEID (WINAPI *mciGetDeviceIDFromElementIDW_type)( DWORD dwElementID, LPCWSTR lpstrType );
+extern mciGetDeviceIDFromElementIDW_type mciGetDeviceIDFromElementIDW_orig;
+typedef DWORD_PTR (WINAPI *mciGetDriverData_type)(UINT uDeviceID);
+extern mciGetDriverData_type mciGetDriverData_orig;
+typedef BOOL (WINAPI *mciGetErrorStringA_type)( MCIERROR mcierr, LPSTR pszText, UINT cchText);
+extern mciGetErrorStringA_type mciGetErrorStringA_orig;
+typedef BOOL (WINAPI *mciGetErrorStringW_type)( MCIERROR mcierr, LPWSTR pszText, UINT cchText);
+extern mciGetErrorStringW_type mciGetErrorStringW_orig;
+typedef BOOL (WINAPI *mciSetDriverData_type)(UINT uDeviceID, DWORD_PTR dwData);
+extern mciSetDriverData_type mciSetDriverData_orig;
+typedef BOOL (WINAPI *mciSetYieldProc_type)( MCIDEVICEID mciId, YIELDPROC fpYieldProc, DWORD dwYieldData);
+extern mciSetYieldProc_type mciSetYieldProc_orig;
+typedef BOOL (WINAPI *mciFreeCommandResource_type)(UINT uTable);
+extern mciFreeCommandResource_type mciFreeCommandResource_orig;
+typedef HTASK (WINAPI *mciGetCreatorTask_type)( MCIDEVICEID mciId);
+extern mciGetCreatorTask_type mciGetCreatorTask_orig;
+typedef YIELDPROC (WINAPI *mciGetYieldProc_type)( MCIDEVICEID mciId, LPDWORD pdwYieldData);
+extern mciGetYieldProc_type mciGetYieldProc_orig;
+typedef UINT (WINAPI *mciLoadCommandResource_type)(HINSTANCE hInstance, LPCWSTR lpResName, UINT uType);
+extern mciLoadCommandResource_type mciLoadCommandResource_orig;
+typedef BOOL (WINAPI *mciExecute_type)(LPCSTR pszCommand);
+extern mciExecute_type mciExecute_orig;
diff --git a/indra/media_plugins/winmmshim/winmm.def b/indra/media_plugins/winmmshim/winmm.def
new file mode 100644
index 0000000000..c55a2845f8
--- /dev/null
+++ b/indra/media_plugins/winmmshim/winmm.def
@@ -0,0 +1,218 @@
+;
+; winmm.def
+;
+; Exports for WINMM DLL
+;
+
+LIBRARY WINMM
+EXPORTS
+CloseDriver
+DefDriverProc
+DriverCallback
+DrvGetModuleHandle
+GetDriverModuleHandle
+;MigrateAllDrivers
+;MigrateSoundEvents
+;NotifyCallbackData
+OpenDriver
+;PlaySound
+PlaySoundA
+PlaySoundW
+SendDriverMessage
+;WOW32DriverCallback
+;WOW32ResolveMultiMediaHandle
+;WOWAppExit
+;WinmmLogoff
+;WinmmLogon
+;aux32Message
+auxGetDevCapsA
+auxGetDevCapsW
+auxGetNumDevs
+auxGetVolume
+auxOutMessage
+auxSetVolume
+;gfxAddGfx
+;gfxBatchChange
+;gfxCreateGfxFactoriesList
+;gfxCreateZoneFactoriesList
+;gfxDestroyDeviceInterfaceList
+;gfxEnumerateGfxs
+;gfxLogoff
+;gfxLogon
+;gfxModifyGfx
+;gfxOpenGfx
+;gfxRemoveGfx
+;joy32Message
+joyConfigChanged
+joyGetDevCapsA
+joyGetDevCapsW
+joyGetNumDevs
+joyGetPos
+joyGetPosEx
+joyGetThreshold
+joyReleaseCapture
+joySetCapture
+joySetThreshold
+;mci32Message
+mciDriverNotify
+mciDriverYield
+mciExecute
+mciFreeCommandResource
+mciGetCreatorTask
+mciGetDeviceIDA
+mciGetDeviceIDFromElementIDA
+mciGetDeviceIDFromElementIDW
+mciGetDeviceIDW
+mciGetDriverData
+mciGetErrorStringA
+mciGetErrorStringW
+mciGetYieldProc
+mciLoadCommandResource
+mciSendCommandA
+mciSendCommandW
+mciSendStringA
+mciSendStringW
+mciSetDriverData
+mciSetYieldProc
+;mid32Message
+midiConnect
+midiDisconnect
+midiInAddBuffer
+midiInClose
+midiInGetDevCapsA
+midiInGetDevCapsW
+midiInGetErrorTextA
+midiInGetErrorTextW
+midiInGetID
+midiInGetNumDevs
+midiInMessage
+midiInOpen
+midiInPrepareHeader
+midiInReset
+midiInStart
+midiInStop
+midiInUnprepareHeader
+midiOutCacheDrumPatches
+midiOutCachePatches
+midiOutClose
+midiOutGetDevCapsA
+midiOutGetDevCapsW
+midiOutGetErrorTextA
+midiOutGetErrorTextW
+midiOutGetID
+midiOutGetNumDevs
+midiOutGetVolume
+midiOutLongMsg
+midiOutMessage
+midiOutOpen
+midiOutPrepareHeader
+midiOutReset
+midiOutSetVolume
+midiOutShortMsg
+midiOutUnprepareHeader
+midiStreamClose
+midiStreamOpen
+midiStreamOut
+midiStreamPause
+midiStreamPosition
+midiStreamProperty
+midiStreamRestart
+midiStreamStop
+mixerClose
+mixerGetControlDetailsA
+mixerGetControlDetailsW
+mixerGetDevCapsA
+mixerGetDevCapsW
+mixerGetID
+mixerGetLineControlsA
+mixerGetLineControlsW
+mixerGetLineInfoA
+mixerGetLineInfoW
+mixerGetNumDevs
+mixerMessage
+mixerOpen
+mixerSetControlDetails
+;mmDrvInstall
+mmGetCurrentTask
+mmTaskBlock
+mmTaskCreate
+mmTaskSignal
+mmTaskYield
+mmioAdvance
+mmioAscend
+mmioClose
+mmioCreateChunk
+mmioDescend
+mmioFlush
+mmioGetInfo
+mmioInstallIOProcA
+mmioInstallIOProcW
+mmioOpenA
+mmioOpenW
+mmioRead
+mmioRenameA
+mmioRenameW
+mmioSeek
+mmioSendMessage
+mmioSetBuffer
+mmioSetInfo
+mmioStringToFOURCCA
+mmioStringToFOURCCW
+mmioWrite
+mmsystemGetVersion
+;mod32Message
+;mxd32Message
+sndPlaySoundA
+sndPlaySoundW
+;tid32Message
+timeBeginPeriod
+timeEndPeriod
+timeGetDevCaps
+timeGetSystemTime
+timeGetTime
+timeKillEvent
+timeSetEvent
+waveInAddBuffer
+waveInClose
+waveInGetDevCapsA
+waveInGetDevCapsW
+waveInGetErrorTextA
+waveInGetErrorTextW
+waveInGetID
+waveInGetNumDevs
+waveInGetPosition
+waveInMessage
+waveInOpen
+waveInPrepareHeader
+waveInReset
+waveInStart
+waveInStop
+waveInUnprepareHeader
+waveOutBreakLoop
+waveOutClose
+waveOutGetDevCapsA
+waveOutGetDevCapsW
+waveOutGetErrorTextA
+waveOutGetErrorTextW
+waveOutGetID
+waveOutGetNumDevs
+waveOutGetPitch
+waveOutGetPlaybackRate
+waveOutGetPosition
+waveOutGetVolume
+waveOutMessage
+waveOutOpen
+waveOutPause
+waveOutPrepareHeader
+waveOutReset
+waveOutRestart
+waveOutSetPitch
+waveOutSetPlaybackRate
+waveOutSetVolume
+waveOutUnprepareHeader
+waveOutWrite
+;wid32Message
+;winmmSetDebugLevel
+;wod32Message
+setPluginVolume
+setPluginMute \ No newline at end of file
diff --git a/indra/media_plugins/winmmshim/winmm_shim.cpp b/indra/media_plugins/winmmshim/winmm_shim.cpp
new file mode 100644
index 0000000000..9563a3b664
--- /dev/null
+++ b/indra/media_plugins/winmmshim/winmm_shim.cpp
@@ -0,0 +1,188 @@
+/**
+ * @file winmmshim.cpp
+ * @brief controls volume level of process by intercepting calls to winmm.dll
+ *
+ * $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$
+ */
+#include "forwarding_api.h"
+#include <xmmintrin.h>
+#include <map>
+#include <math.h>
+
+using std::wstring;
+
+static float sVolumeLevel = 1.f;
+static bool sMute = false;
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ static bool initialized = false;
+ // do this only once
+ if (!initialized)
+ { // bind to original winmm.dll
+ TCHAR system_path[MAX_PATH];
+ TCHAR dll_path[MAX_PATH];
+ ::GetSystemDirectory(system_path, MAX_PATH);
+
+ // grab winmm.dll from system path, where it should live
+ wsprintf(dll_path, "%s\\winmm.dll", system_path);
+ HMODULE winmm_handle = ::LoadLibrary(dll_path);
+
+ if (winmm_handle != NULL)
+ { // we have a dll, let's get out pointers!
+ initialized = true;
+ init_function_pointers(winmm_handle);
+ return true;
+ }
+
+ // failed to initialize real winmm.dll
+ return false;
+ }
+ return true;
+}
+
+
+extern "C"
+{
+ // tracks the requested format for a given waveout buffer
+ struct WaveOutFormat
+ {
+ WaveOutFormat(int bits_per_sample)
+ : mBitsPerSample(bits_per_sample)
+ {}
+ int mBitsPerSample;
+ };
+ typedef std::map<HWAVEOUT, WaveOutFormat*> wave_out_map_t;
+ static wave_out_map_t sWaveOuts;
+
+ MMRESULT WINAPI waveOutOpen( LPHWAVEOUT phwo, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen)
+ {
+ if (pwfx->wFormatTag != WAVE_FORMAT_PCM
+ || (pwfx->wBitsPerSample != 8 && pwfx->wBitsPerSample != 16))
+ { // uncompressed 8 and 16 bit sound are the only types we support
+ return WAVERR_BADFORMAT;
+ }
+
+ MMRESULT result = waveOutOpen_orig(phwo, uDeviceID, pwfx, dwCallback, dwInstance, fdwOpen);
+ if (result == MMSYSERR_NOERROR
+ && ((fdwOpen & WAVE_FORMAT_QUERY) == 0)) // not just querying for format support
+ { // remember the requested bits per sample, and associate with the given handle
+ WaveOutFormat* wave_outp = new WaveOutFormat(pwfx->wBitsPerSample);
+ sWaveOuts.insert(std::make_pair(*phwo, wave_outp));
+ }
+ return result;
+ }
+
+ MMRESULT WINAPI waveOutClose( HWAVEOUT hwo)
+ {
+ wave_out_map_t::iterator found_it = sWaveOuts.find(hwo);
+ if (found_it != sWaveOuts.end())
+ { // forget what we know about this handle
+ delete found_it->second;
+ sWaveOuts.erase(found_it);
+ }
+ return waveOutClose_orig( hwo);
+ }
+
+ MMRESULT WINAPI waveOutWrite( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh)
+ {
+ MMRESULT result = MMSYSERR_NOERROR;
+
+ if (sMute)
+ { // zero out the audio buffer when muted
+ memset(pwh->lpData, 0, pwh->dwBufferLength);
+ }
+ else if (sVolumeLevel != 1.f)
+ { // need to apply volume level
+ wave_out_map_t::iterator found_it = sWaveOuts.find(hwo);
+ if (found_it != sWaveOuts.end())
+ {
+ WaveOutFormat* formatp = found_it->second;
+ switch (formatp->mBitsPerSample){
+ case 8:
+ {
+ char volume = (char)(sVolumeLevel * 127.f);
+ for (unsigned int i = 0; i < pwh->dwBufferLength; i++)
+ {
+ // unsigned multiply doesn't use most significant bit, so shift by 7 bits
+ // to get resulting value back into 8 bits
+ pwh->lpData[i] = (pwh->lpData[i] * volume) >> 7;
+ }
+ break;
+ }
+ case 16:
+ {
+ short volume_16 = (short)(sVolumeLevel * 32767.f);
+
+ // copy volume level 4 times into 64 bit MMX register
+ __m64 volume_64 = _mm_set_pi16(volume_16, volume_16, volume_16, volume_16);
+ __m64* sample_64;
+ __m64* last_sample_64 = (__m64*)(pwh->lpData + pwh->dwBufferLength - sizeof(__m64));
+ // for everything that can be addressed in 64 bit multiples...
+ for (sample_64 = (__m64*)pwh->lpData;
+ sample_64 <= last_sample_64;
+ ++sample_64)
+ {
+ //...multiply the samples by the volume...
+ __m64 scaled_sample = _mm_mulhi_pi16(*sample_64, volume_64);
+ // ...and shift left 1 bit since an unsigned multiple loses the most significant bit
+ // 0x7FFF * 0x7FFF = 0x3fff0001
+ // 0x3fff0001 << 1 = 0x7ffe0002
+ // notice that the LSB is always 0...should consider dithering
+ *sample_64 = _mm_slli_pi16(scaled_sample, 1);
+ }
+
+ // the captain has turned off the MMX sign, you are now free to use floating point registers
+ _mm_empty();
+
+ // finish remaining samples that didn't fit into 64 bit register
+ for (short* sample_16 = (short*)sample_64;
+ sample_16 < (short*)(pwh->lpData + pwh->dwBufferLength);
+ ++sample_16)
+ {
+ *sample_16 = (*sample_16 * volume_16) >> 15;
+ }
+
+ break;
+ }
+ default:
+ // don't do anything
+ break;
+ }
+ }
+ }
+ return waveOutWrite_orig( hwo, pwh, cbwh);
+ }
+
+ void WINAPI setPluginVolume(float volume)
+ {
+ sVolumeLevel = volume;
+ }
+
+ void WINAPI setPluginMute(bool mute)
+ {
+ sMute = mute;
+ }
+}