diff options
Diffstat (limited to 'indra/media_plugins')
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; + } +} |