Skip to content
Snippets Groups Projects
Commit 8a12a4c9 authored by Oz Linden's avatar Oz Linden
Browse files

merge callum fixes

parents fad899fe 4ca084f7
No related branches found
No related tags found
No related merge requests found
......@@ -686,9 +686,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>23876d471ef04d28b73a931057758872</string>
<string>ad5bb66f2aaa12636b5a69a020ea9f18</string>
<key>url</key>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/358/899/fmodex-4.44.61.500350-windows-500350.tar.bz2</string>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1191/2796/fmodex-4.44.61.501175-windows-501175.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
......@@ -698,16 +698,16 @@
<key>archive</key>
<map>
<key>hash</key>
<string>f87fd527e1cca5b1b64090c5afb04cdb</string>
<string>6722f0efc2b55542bd71514b9a09e377</string>
<key>url</key>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/357/896/fmodex-4.44.61.500350-windows64-500350.tar.bz2</string>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1190/2791/fmodex-4.44.61.501175-windows64-501175.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
<string>4.44.61.500350</string>
<string>4.44.61.501175</string>
</map>
<key>fontconfig</key>
<map>
......@@ -1358,9 +1358,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>96b6b1a0ae2c2ac9dfa44b444f71117a</string>
<string>dab55cc0555d7126fda925e20af851ea</string>
<key>url</key>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/752/1566/havok_source-2012.1-2-windows-500739.tar.bz2</string>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1194/2807/havok_source-2012.1-2-windows-501181.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
......@@ -1370,9 +1370,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>5db6f7f8a86fa2297f2c7c86d7491042</string>
<string>7bbc1c3512a5665b7576b4b0357a9eb7</string>
<key>url</key>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/751/1558/havok_source-2012.1-2-windows64-500739.tar.bz2</string>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1195/2816/havok_source-2012.1-2-windows64-501181.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
......
......@@ -13,6 +13,5 @@ endif (DARWIN)
if (WINDOWS)
add_subdirectory(cef)
add_subdirectory(winmmshim)
add_subdirectory(libvlc)
endif (WINDOWS)
......@@ -42,44 +42,15 @@ friend LLSingleton<VolumeCatcherImpl>;
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;
// tests if running on Vista, 7, 8 + once in CTOR
bool isWindowsVistaOrHigher();
F32 mVolume;
F32 mPan;
bool mSystemIsVistaOrHigher;
};
bool VolumeCatcherImpl::isWindowsVistaOrHigher()
{
OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
return osvi.dwMajorVersion >= 6;
}
VolumeCatcherImpl::VolumeCatcherImpl()
: mVolume(1.0f), // default volume is max
mPan(0.f) // default pan is centered
{
mSystemIsVistaOrHigher = isWindowsVistaOrHigher();
if ( ! mSystemIsVistaOrHigher )
{
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()
......@@ -90,26 +61,12 @@ void VolumeCatcherImpl::setVolume(F32 volume)
{
mVolume = volume;
if ( mSystemIsVistaOrHigher )
{
// set both left/right to same volume
// TODO: use pan value to set independently
DWORD left_channel = (DWORD)(mVolume * 65535.0f);
DWORD right_channel = (DWORD)(mVolume * 65535.0f);
DWORD hw_volume = left_channel << 16 | right_channel;
::waveOutSetVolume(NULL, hw_volume);
}
else
{
if (mSetMuteFunc)
{
mSetMuteFunc(volume == 0.f);
}
if (mSetVolumeFunc)
{
mSetVolumeFunc(mVolume);
}
}
// set both left/right to same volume
// TODO: use pan value to set independently
DWORD left_channel = (DWORD)(mVolume * 65535.0f);
DWORD right_channel = (DWORD)(mVolume * 65535.0f);
DWORD hw_volume = left_channel << 16 | right_channel;
::waveOutSetVolume(NULL, hw_volume);
}
void VolumeCatcherImpl::setPan(F32 pan)
......
# -*- cmake -*-
project(winmm_shim)
### winmm_shim
# *HACK - override msvcrt implementation (intialized on 00-Common) to be
# statically linked for winmm.dll this relies on vc taking the last flag on
# the command line
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MT")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
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})
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)
This diff is collapsed.
This diff is collapsed.
;
; 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
/**
* @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-2014, 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; // Could be covered by critical section,
static bool sMute = false; // not needed with atomicity and alignment.
static CRITICAL_SECTION sCriticalSection;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
InitializeCriticalSection(&sCriticalSection);
}
return TRUE;
}
void ll_winmm_shim_initialize(){
static volatile bool initialized = false;
// do this only once using double-check locking
if (!initialized)
{
EnterCriticalSection(&sCriticalSection);
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!
init_function_pointers(winmm_handle);
::OutputDebugStringA("WINMM_SHIM.DLL: real winmm.dll initialized successfully\n");
initialized = true; // Last thing after completing setup
}
else
{
// failed to initialize real winmm.dll
::OutputDebugStringA("WINMM_SHIM.DLL: Failed to initialize real winmm.dll\n");
}
}
LeaveCriticalSection(&sCriticalSection);
}
}
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; // Covered by sCriticalSection
MMRESULT WINAPI waveOutOpen( LPHWAVEOUT phwo, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen)
{
ll_winmm_shim_initialize();
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);
EnterCriticalSection(&sCriticalSection);
sWaveOuts.insert(std::make_pair(*phwo, wave_outp));
LeaveCriticalSection(&sCriticalSection);
}
return result;
}
MMRESULT WINAPI waveOutClose( HWAVEOUT hwo)
{
ll_winmm_shim_initialize();
EnterCriticalSection(&sCriticalSection);
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);
}
LeaveCriticalSection(&sCriticalSection);
return waveOutClose_orig(hwo);
}
MMRESULT WINAPI waveOutWrite( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh)
{
ll_winmm_shim_initialize();
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
int bits_per_sample(0);
EnterCriticalSection(&sCriticalSection);
wave_out_map_t::iterator found_it = sWaveOuts.find(hwo);
if (found_it != sWaveOuts.end())
{
bits_per_sample = found_it->second->mBitsPerSample;
}
LeaveCriticalSection(&sCriticalSection);
if (bits_per_sample)
{
switch (bits_per_sample)
{
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;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment