commit 9a97b961814210fe6eae49d6b76823a0c7763ff7 Author: jthedering <51533355+jthedering@users.noreply.github.com> Date: Tue Sep 18 22:13:36 2012 +0000 diff --git a/Benchmark/Benchmark.cpp b/Benchmark/Benchmark.cpp new file mode 100644 index 0000000..2955dd9 --- /dev/null +++ b/Benchmark/Benchmark.cpp @@ -0,0 +1,115 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#define _USE_MATH_DEFINES +#include +#include + +#include "../ParametricEQ.h" +#include "PerformanceCounter.h" + +using namespace std; + +const int BATCH_SIZE = 65536; + +int main(int argc, char** argv) +{ + unsigned sampleRate; + unsigned channelCount; + unsigned frameCount; + float* buf; + + if(argc >= 2 && strlen(argv[1]) > 0) + { + SF_INFO info; + printf("Reading sound data from %s\n", argv[1]); + SNDFILE* inFile = sf_open(argv[1], SFM_READ, &info); + + sampleRate = info.samplerate; + channelCount = info.channels; + frameCount = (unsigned)info.frames; + + buf = new float[frameCount * channelCount]; + + sf_count_t numRead = 0; + while(numRead < frameCount) + numRead += sf_readf_float(inFile, buf + numRead * channelCount, frameCount - numRead); + + sf_close(inFile); + inFile = NULL; + } + else + { + sampleRate = 44100; + channelCount = 1; + frameCount = 8820000; + float sweepFrom = 0.1f; + float sweepTo = 20000; + float sweepDiff = sweepTo - sweepFrom; + float length = 200; + + printf("No input file given, so generating linear sine sweep from %g to %g Hz over %g seconds\n", sweepFrom, sweepTo, length); + + buf = new float[frameCount * channelCount]; + + for(unsigned i=0;i= 3 && strlen(argv[2]) > 0) + outPath = argv[2]; + printf("Writing output to %s\n", outPath); + + SF_INFO info = {frameCount, sampleRate, channelCount, SF_FORMAT_WAV | SF_FORMAT_PCM_16, 0}; + SNDFILE* outFile = sf_open(outPath, SFM_WRITE, &info); + + sf_count_t numWritten = 0; + while(numWritten < frameCount) + numWritten += sf_writef_float(outFile, buf + numWritten * channelCount, frameCount - numWritten); + + sf_close(outFile); + outFile = NULL; + + delete[] buf; + + return 0; +} diff --git a/Benchmark/Benchmark.vcxproj b/Benchmark/Benchmark.vcxproj new file mode 100644 index 0000000..cf799f7 --- /dev/null +++ b/Benchmark/Benchmark.vcxproj @@ -0,0 +1,164 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {D4474852-5724-4253-95C6-7A6DC424F194} + Win32Proj + Benchmark + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + C:\Program Files\libsndfile\include;$(IncludePath) + C:\Program Files\libsndfile\lib;$(LibraryPath) + + + true + C:\Program Files\libsndfile\include;$(IncludePath) + C:\Program Files\libsndfile\lib;$(LibraryPath) + + + false + C:\Program Files\libsndfile\include;$(IncludePath) + C:\Program Files\libsndfile\lib;$(LibraryPath) + + + false + C:\Program Files\libsndfile\include;$(IncludePath) + C:\Program Files\libsndfile\lib64;$(LibraryPath) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + Shlwapi.lib;libsndfile-1.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + Shlwapi.lib;libsndfile-1.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + Shlwapi.lib;libsndfile-1.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + Shlwapi.lib;libsndfile-1.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Benchmark/PerformanceCounter.h b/Benchmark/PerformanceCounter.h new file mode 100644 index 0000000..378c8f8 --- /dev/null +++ b/Benchmark/PerformanceCounter.h @@ -0,0 +1,48 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#pragma once + +#define WIN32_LEAN_AND_MEAN +#include + +class PrecisionTimer +{ + LARGE_INTEGER freq; + LARGE_INTEGER startCount; + +public: + PrecisionTimer() + { + QueryPerformanceFrequency(&freq); + } + + void start() + { + QueryPerformanceCounter(&startCount); + } + + double stop() + { + LARGE_INTEGER stopCount; + QueryPerformanceCounter(&stopCount); + + return double(stopCount.QuadPart - startCount.QuadPart) / freq.QuadPart; + } +}; diff --git a/ClassFactory.cpp b/ClassFactory.cpp new file mode 100644 index 0000000..dcda3e7 --- /dev/null +++ b/ClassFactory.cpp @@ -0,0 +1,84 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "EqualizerAPO.h" +#include "LogHelper.h" +#include "ClassFactory.h" + +long ClassFactory::lockCount = 0; + +ClassFactory::ClassFactory() +{ + refCount = 1; +} + +HRESULT __stdcall ClassFactory::QueryInterface(const IID& iid, void** ppv) +{ + if(iid == __uuidof(IUnknown) || iid == __uuidof(IClassFactory)) + *ppv = static_cast(this); + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + + reinterpret_cast(*ppv)->AddRef(); + return S_OK; +} + +ULONG __stdcall ClassFactory::AddRef() +{ + return InterlockedIncrement(&refCount); +} + +ULONG __stdcall ClassFactory::Release() +{ + if(InterlockedDecrement(&refCount) == 0) + { + delete this; + return 0; + } + + return refCount; +} + +HRESULT __stdcall ClassFactory::CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv) +{ + if(pUnknownOuter != NULL && iid != __uuidof(IUnknown)) + return E_NOINTERFACE; + + EqualizerAPO* apo = new EqualizerAPO(pUnknownOuter); + if(apo == NULL) + return E_OUTOFMEMORY; + + HRESULT hr = apo->NonDelegatingQueryInterface(iid, ppv); + + apo->NonDelegatingRelease(); + return hr; +} + +HRESULT __stdcall ClassFactory::LockServer(BOOL bLock) +{ + if(bLock) + InterlockedIncrement(&lockCount); + else + InterlockedDecrement(&lockCount); + + return S_OK; +} diff --git a/ClassFactory.h b/ClassFactory.h new file mode 100644 index 0000000..f694144 --- /dev/null +++ b/ClassFactory.h @@ -0,0 +1,41 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#pragma once + +#include + +class ClassFactory: public IClassFactory +{ +public: + ClassFactory(); + + // IUnknown + virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv); + virtual ULONG __stdcall AddRef(); + virtual ULONG __stdcall Release(); + + // IClassFactory + virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv); + virtual HRESULT __stdcall LockServer(BOOL bLock); + + static long lockCount; +private: + long refCount; +}; diff --git a/Configurator/Configurator.cpp b/Configurator/Configurator.cpp new file mode 100644 index 0000000..7cf55c6 --- /dev/null +++ b/Configurator/Configurator.cpp @@ -0,0 +1,251 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include "../RegistryHelper.h" +#include "Configurator.h" + +using namespace std; + +Configurator* configurator; + +Configurator::Configurator(HINSTANCE hInstance, const wchar_t* cmdLine) + :cmdLine(cmdLine) +{ + this->hInstance = hInstance; + hDlg = NULL; +} + +void Configurator::onInitDialog(HWND hDlg) +{ + this->hDlg = hDlg; + deviceList = GetDlgItem(hDlg, IDC_DEVICE_LIST); + okButton = GetDlgItem(hDlg, IDOK); + cancelButton = GetDlgItem(hDlg, IDCANCEL); + requestLabel = GetDlgItem(hDlg, IDC_REQUEST); + + wchar_t stringBuf[255]; + LoadStringW(hInstance, IDS_REQUEST, stringBuf, sizeof(stringBuf)/sizeof(wchar_t)); + SetWindowTextW(requestLabel, stringBuf); + + ListView_SetExtendedListViewStyle(deviceList, ListView_GetExtendedListViewStyle(deviceList) | LVS_EX_CHECKBOXES); + LVCOLUMN column; + column.pszText = stringBuf; + column.mask = LVCF_TEXT; + + LoadStringW(hInstance, IDS_CONNECTOR, stringBuf, sizeof(stringBuf)/sizeof(wchar_t)); + ListView_InsertColumn(deviceList, 0, &column); + + LoadStringW(hInstance, IDS_DEVICE, stringBuf, sizeof(stringBuf)/sizeof(wchar_t)); + ListView_InsertColumn(deviceList, 1, &column); + + LoadStringW(hInstance, IDS_STATUS, stringBuf, sizeof(stringBuf)/sizeof(wchar_t)); + ListView_InsertColumn(deviceList, 2, &column); + + LVITEM item; + item.iSubItem = 0; + item.pszText = stringBuf; + item.mask = LVIF_TEXT | LVIF_PARAM; + + try { + apoInfos = DeviceAPOInfo::loadAllInfos(); + + int itemCount=0; + for(vector::iterator it = apoInfos.begin(); it != apoInfos.end(); it++) + { + wcsncpy_s(stringBuf, sizeof(stringBuf)/sizeof(wchar_t), it->connectionName.c_str(), _TRUNCATE); + item.iItem = itemCount; + item.lParam = itemCount; + ListView_InsertItem(deviceList, &item); + wcsncpy_s(stringBuf, sizeof(stringBuf)/sizeof(wchar_t), it->deviceName.c_str(), _TRUNCATE); + ListView_SetItemText(deviceList, itemCount, 1, stringBuf); + + if(it->isInstalled) + { + ListView_SetCheckState(deviceList, itemCount, TRUE); + LoadStringW(hInstance, IDS_ALREADY_INSTALLED, stringBuf, sizeof(stringBuf)/sizeof(wchar_t)); + ListView_SetItemText(deviceList, itemCount, 2, stringBuf); + } + else + { + LoadStringW(hInstance, IDS_CAN_BE_INSTALLED, stringBuf, sizeof(stringBuf)/sizeof(wchar_t)); + ListView_SetItemText(deviceList, itemCount, 2, stringBuf); + } + + itemCount++; + } + } + catch(RegistryException e) + { + MessageBoxW(hDlg, e.getMessage().c_str(), L"Error while accessing the registry", MB_ICONERROR | MB_OK); + } + + ListView_SetColumnWidth(deviceList, 0, LVSCW_AUTOSIZE); + ListView_SetColumnWidth(deviceList, 1, LVSCW_AUTOSIZE); + ListView_SetColumnWidth(deviceList, 2, LVSCW_AUTOSIZE); +} + +void Configurator::onLvnItemChanged(unsigned sourceId, LPNMLISTVIEW info) +{ + int itemCount = ListView_GetItemCount(deviceList); + + if(apoInfos.size() == itemCount) + { + DeviceAPOInfo apoInfo = apoInfos[info->lParam]; + bool checked = ListView_GetCheckState(deviceList,info->iItem) != 0; + wchar_t stringBuf[255]; + if(checked && !apoInfo.isInstalled) + LoadStringW(hInstance, IDS_WILL_BE_INSTALLED, stringBuf, sizeof(stringBuf)/sizeof(wchar_t)); + else if(!checked && apoInfo.isInstalled) + LoadStringW(hInstance, IDS_WILL_BE_UNINSTALLED, stringBuf, sizeof(stringBuf)/sizeof(wchar_t)); + else if(apoInfo.isInstalled) + LoadStringW(hInstance, IDS_ALREADY_INSTALLED, stringBuf, sizeof(stringBuf)/sizeof(wchar_t)); + else + LoadStringW(hInstance, IDS_CAN_BE_INSTALLED, stringBuf, sizeof(stringBuf)/sizeof(wchar_t)); + + ListView_SetItemText(deviceList, info->iItem, 2, stringBuf); + + bool changed = false; + for(int i = 0; i < itemCount; i++) + { + LVITEM item; + item.iItem = i; + item.iSubItem = 0; + item.mask = LVIF_PARAM; + ListView_GetItem(deviceList, &item); + if((ListView_GetCheckState(deviceList, i) != 0) != apoInfos[item.lParam].isInstalled) + { + changed = true; + break; + } + } + + EnableWindow(okButton, changed); + } +} + +void Configurator::onButtonClicked(unsigned sourceId) +{ + if(sourceId == IDOK) + { + try + { + for(int i = 0; i < ListView_GetItemCount(deviceList); i++) + { + LVITEM item; + item.iItem = i; + item.iSubItem = 0; + item.mask = LVIF_PARAM; + ListView_GetItem(deviceList, &item); + + DeviceAPOInfo info = apoInfos[item.lParam]; + if(ListView_GetCheckState(deviceList, i) && !info.isInstalled) + info.install(); + else if(!ListView_GetCheckState(deviceList, i) && info.isInstalled) + info.uninstall(); + } + } + catch(RegistryException e) + { + MessageBoxW(hDlg, e.getMessage().c_str(), L"Error while accessing the registry", MB_ICONERROR | MB_OK); + } + } + + if(cmdLine == L"/i") + { + wchar_t stringBuf[255]; + LoadStringW(hInstance, IDS_AFTERINSTALL, stringBuf, sizeof(stringBuf)/sizeof(wchar_t)); + MessageBoxW(hDlg, stringBuf, L"Info", MB_ICONINFORMATION | MB_OK); + } +} + +INT_PTR CALLBACK dlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + +int APIENTRY wWinMain(HINSTANCE hInstance, + HINSTANCE /* hPrevInstance */, + LPWSTR lpCmdLine, + int nCmdShow) +{ + INITCOMMONCONTROLSEX InitCtrls; + InitCtrls.dwSize = sizeof(InitCtrls); + InitCtrls.dwICC = ICC_WIN95_CLASSES; + InitCommonControlsEx(&InitCtrls); + + int result = 0; + + if(wcscmp(lpCmdLine, L"/u") == 0) + { + vector apoInfos = DeviceAPOInfo::loadAllInfos(); + + for(vector::iterator it = apoInfos.begin(); it != apoInfos.end(); it++) + { + try + { + if(it->isInstalled) + it->uninstall(); + } + catch (RegistryException e) + { + MessageBoxW(NULL, e.getMessage().c_str(), NULL, MB_ICONERROR | MB_OK); + result = -1; + } + } + } + else + { + configurator = new Configurator(hInstance, lpCmdLine); + DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAINWINDOW), GetDesktopWindow(), dlgProc); + } + + return result; +} + +INT_PTR CALLBACK dlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + UNREFERENCED_PARAMETER(lParam); + switch (message) + { + case WM_INITDIALOG: + configurator->onInitDialog(hDlg); + + return (INT_PTR)TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) + { + configurator->onButtonClicked(LOWORD(wParam)); + + EndDialog(hDlg, LOWORD(wParam)); + return (INT_PTR)TRUE; + } + break; + + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->code) + { + case LVN_ITEMCHANGED: + configurator->onLvnItemChanged((unsigned)((LPNMHDR)lParam)->idFrom, (LPNMLISTVIEW) lParam); + break; + } + break; + } + return (INT_PTR)FALSE; +} diff --git a/Configurator/Configurator.exe.manifest b/Configurator/Configurator.exe.manifest new file mode 100644 index 0000000..e65d685 --- /dev/null +++ b/Configurator/Configurator.exe.manifest @@ -0,0 +1,31 @@ + + + +Equalizer APO configuration utility + + + + + + + + + + + + + diff --git a/Configurator/Configurator.h b/Configurator/Configurator.h new file mode 100644 index 0000000..5726ab6 --- /dev/null +++ b/Configurator/Configurator.h @@ -0,0 +1,45 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#pragma once + +#include "resource.h" +#include +#include +#include "DeviceAPOInfo.h" + +class Configurator +{ +public: + Configurator(HINSTANCE hInstance, const wchar_t* cmdLine); + void onInitDialog(HWND hDlg); + void onLvnItemChanged(unsigned sourceId, LPNMLISTVIEW info); + void onButtonClicked(unsigned sourceId); + +private: + HINSTANCE hInstance; + HWND hDlg; + HWND deviceList; + HWND okButton; + HWND cancelButton; + HWND requestLabel; + std::wstring cmdLine; + + std::vector apoInfos; +}; diff --git a/Configurator/Configurator.ico b/Configurator/Configurator.ico new file mode 100644 index 0000000..d551aa3 Binary files /dev/null and b/Configurator/Configurator.ico differ diff --git a/Configurator/Configurator.rc b/Configurator/Configurator.rc new file mode 100644 index 0000000..b848a81 Binary files /dev/null and b/Configurator/Configurator.rc differ diff --git a/Configurator/Configurator.vcxproj b/Configurator/Configurator.vcxproj new file mode 100644 index 0000000..2752ad5 --- /dev/null +++ b/Configurator/Configurator.vcxproj @@ -0,0 +1,171 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + Designer + + + + {E18E1CA7-3D6C-4CD5-9CE9-E72565A206E5} + Win32Proj + Configurator + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(IncludePath);$(DDK_PATH)\inc\api + false + + + true + $(IncludePath);$(DDK_PATH)\inc\api + false + + + false + $(IncludePath);$(DDK_PATH)\inc\api + false + + + false + $(IncludePath);$(DDK_PATH)\inc\api + false + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + comctl32.lib;%(AdditionalDependencies) + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + comctl32.lib;%(AdditionalDependencies) + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + true + true + comctl32.lib;%(AdditionalDependencies) + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + true + true + comctl32.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/Configurator/DeviceAPOInfo.cpp b/Configurator/DeviceAPOInfo.cpp new file mode 100644 index 0000000..5809ec4 --- /dev/null +++ b/Configurator/DeviceAPOInfo.cpp @@ -0,0 +1,86 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "DeviceAPOInfo.h" + +#include "../EqualizerAPO.h" +#include "../ParametricEQ.h" +#include "../RegistryHelper.h" + +using namespace std; + +#define renderKeyPath L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\MMDevices\\Audio\\Render" +static const wchar_t* connectionValueName = L"{a45c254e-df1c-4efd-8020-67d146a850e0},2"; +static const wchar_t* deviceValueName = L"{b3f8fa53-0004-438e-9003-51a46e139bfc},6"; +static const wchar_t* apoGuidValueName = L"{d04e05a6-594b-4fb6-a80d-01af5eed7d1d},1"; + +vector DeviceAPOInfo::loadAllInfos() +{ + vector result; + vector deviceGuidStrings = RegistryHelper::enumSubKeys(renderKeyPath); + for(vector::iterator it = deviceGuidStrings.begin(); it != deviceGuidStrings.end(); it++) + { + wstring deviceGuidString = *it; + + if(!RegistryHelper::keyExists(renderKeyPath L"\\" + deviceGuidString + L"\\FxProperties")) + continue; + + wstring connectionName = RegistryHelper::readValue(renderKeyPath L"\\" + deviceGuidString + L"\\Properties", connectionValueName); + wstring deviceName = RegistryHelper::readValue(renderKeyPath L"\\" + deviceGuidString + L"\\Properties", deviceValueName); + wstring apoGuidString = RegistryHelper::readValue(renderKeyPath L"\\" + deviceGuidString + L"\\FxProperties", apoGuidValueName); + + GUID apoGuid; + if(!SUCCEEDED(CLSIDFromString(apoGuidString.c_str(), &apoGuid))) + continue; + + bool installed = false; + if(apoGuid == __uuidof(EqualizerAPO)) + { + installed = true; + } + + DeviceAPOInfo info = {deviceName, connectionName, deviceGuidString, apoGuidString, installed}; + result.push_back(info); + } + + return result; +} + +void DeviceAPOInfo::install() +{ + RegistryHelper::createKey(APP_REGPATH L"\\Child APOs"); + + RegistryHelper::writeValue(APP_REGPATH L"\\Child APOs", deviceGuid, originalApoGuid); + + RegistryHelper::saveToFile(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties", apoGuidValueName, L"backup_" + deviceName + L"_" + connectionName + L".reg"); + + RegistryHelper::writeValue(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties", apoGuidValueName, RegistryHelper::getGuidString(__uuidof(EqualizerAPO))); +} + +void DeviceAPOInfo::uninstall() +{ + wstring originalChildApoGuid = RegistryHelper::readValue(APP_REGPATH L"\\Child APOs", deviceGuid); + + RegistryHelper::writeValue(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties", apoGuidValueName, originalChildApoGuid); + + RegistryHelper::deleteValue(APP_REGPATH L"\\Child APOs", deviceGuid); + + if(RegistryHelper::valueCount(APP_REGPATH L"\\Child APOs") == 0) + RegistryHelper::deleteKey(APP_REGPATH L"\\Child APOs"); +} diff --git a/Configurator/DeviceAPOInfo.h b/Configurator/DeviceAPOInfo.h new file mode 100644 index 0000000..aaf61bc --- /dev/null +++ b/Configurator/DeviceAPOInfo.h @@ -0,0 +1,37 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#pragma once + +#include +#include + +class DeviceAPOInfo +{ +public: + static std::vector loadAllInfos(); + void install(); + void uninstall(); + + std::wstring deviceName; + std::wstring connectionName; + std::wstring deviceGuid; + std::wstring originalApoGuid; + bool isInstalled; +}; diff --git a/Configurator/resource.h b/Configurator/resource.h new file mode 100644 index 0000000..187970e Binary files /dev/null and b/Configurator/resource.h differ diff --git a/Configurator/small.ico b/Configurator/small.ico new file mode 100644 index 0000000..d551aa3 Binary files /dev/null and b/Configurator/small.ico differ diff --git a/DllMain.cpp b/DllMain.cpp new file mode 100644 index 0000000..d4290c4 --- /dev/null +++ b/DllMain.cpp @@ -0,0 +1,112 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#define WIN32_LEAN_AND_MEAN +#include + +#include "EqualizerAPO.h" +#include "ClassFactory.h" +#include "RegistryHelper.h" +#include "LogHelper.h" + +using namespace std; + +static HINSTANCE hModule; + +BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, void* lpReserved) +{ + if(dwReason == DLL_PROCESS_ATTACH) + ::hModule = hModule; + + return TRUE; +} + +STDAPI DllCanUnloadNow() +{ + if(EqualizerAPO::instCount == 0 && ClassFactory::lockCount == 0) + return S_OK; + else + return S_FALSE; +} + +STDAPI DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv) +{ + if(clsid != __uuidof(EqualizerAPO)) + return CLASS_E_CLASSNOTAVAILABLE; + + ClassFactory* factory = new ClassFactory(); + if(factory == NULL) + return E_OUTOFMEMORY; + + HRESULT hr = factory->QueryInterface(iid, ppv); + factory->Release(); + + return hr; +} + +STDAPI DllRegisterServer() +{ + wchar_t filename[1024]; + GetModuleFileNameW(hModule, filename, sizeof(filename)/sizeof(wchar_t)); + + HRESULT hr = RegisterAPO(EqualizerAPO::regProperties); + if(FAILED(hr)) + { + UnregisterAPO(__uuidof(EqualizerAPO)); + return hr; + } + + try + { + wstring apoClsidString = RegistryHelper::getGuidString(__uuidof(EqualizerAPO)); + + RegistryHelper::createKey(L"SOFTWARE\\Classes\\CLSID\\" + apoClsidString); + RegistryHelper::writeValue(L"SOFTWARE\\Classes\\CLSID\\" + apoClsidString, L"", L"EqualizerAPO Class"); + RegistryHelper::createKey(L"SOFTWARE\\Classes\\CLSID\\" + apoClsidString + L"\\InprocServer32"); + RegistryHelper::writeValue(L"SOFTWARE\\Classes\\CLSID\\" + apoClsidString + L"\\InprocServer32", L"", filename); + RegistryHelper::writeValue(L"SOFTWARE\\Classes\\CLSID\\" + apoClsidString + L"\\InprocServer32", L"ThreadingModel", L"Both"); + } + catch(RegistryException e) + { + UnregisterAPO(__uuidof(EqualizerAPO)); + return E_FAIL; + } + + return S_OK; +} + +STDAPI DllUnregisterServer() +{ + try + { + wstring apoClsidString = RegistryHelper::getGuidString(__uuidof(EqualizerAPO)); + + RegistryHelper::deleteKey(L"SOFTWARE\\Classes\\CLSID\\" + apoClsidString + L"\\InprocServer32"); + RegistryHelper::deleteKey(L"SOFTWARE\\Classes\\CLSID\\" + apoClsidString); + } + catch(RegistryException e) + { + return E_FAIL; + } + + HRESULT hr = UnregisterAPO(__uuidof(EqualizerAPO)); + + return hr; +} diff --git a/EqualizerAPO.cpp b/EqualizerAPO.cpp new file mode 100644 index 0000000..a48b751 --- /dev/null +++ b/EqualizerAPO.cpp @@ -0,0 +1,348 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#define INITGUID +#include + +#include "LogHelper.h" +#include "RegistryHelper.h" +#include "EqualizerAPO.h" + +using namespace std; + +long EqualizerAPO::instCount = 0; +const CRegAPOProperties<1> EqualizerAPO::regProperties( + __uuidof(EqualizerAPO), L"EqualizerAPO", L"Copyright (C) 2012", 1, 0, __uuidof(IAudioProcessingObject), + (APO_FLAG)( APO_FLAG_FRAMESPERSECOND_MUST_MATCH | APO_FLAG_BITSPERSAMPLE_MUST_MATCH | APO_FLAG_INPLACE)); + +EqualizerAPO::EqualizerAPO(IUnknown* pUnkOuter) + :CBaseAudioProcessingObject(regProperties) +{ + refCount = 1; + if(pUnkOuter != NULL) + this->pUnkOuter = pUnkOuter; + else + this->pUnkOuter = reinterpret_cast(static_cast(this)); + + childAPO = NULL; + childRT = NULL; + childCfg = NULL; + + InterlockedIncrement(&instCount); +} + +EqualizerAPO::~EqualizerAPO() +{ + InterlockedDecrement(&instCount); +} + +HRESULT EqualizerAPO::QueryInterface(const IID& iid, void** ppv) +{ + return pUnkOuter->QueryInterface(iid, ppv); +} + +ULONG EqualizerAPO::AddRef() +{ + return pUnkOuter->AddRef(); +} + +ULONG EqualizerAPO::Release() +{ + return pUnkOuter->Release(); +} + +HRESULT EqualizerAPO::GetLatency(HNSTIME* pTime) +{ + if(!pTime) + return E_POINTER; + + if(!m_bIsLocked) + return APOERR_ALREADY_UNLOCKED; + + *pTime = 0; + if(childAPO) + childAPO->GetLatency(pTime); + + return S_OK; +} + +HRESULT EqualizerAPO::Initialize(UINT32 cbDataSize, BYTE* pbyData) +{ + LogHelper::reset(); + + TraceF(L"Initialize"); + + if((NULL == pbyData) && (0 != cbDataSize)) + return E_INVALIDARG; + if((NULL != pbyData) && (0 == cbDataSize)) + return E_POINTER; + if(cbDataSize != sizeof(APOInitSystemEffects) ) + return E_INVALIDARG; + + resetChild(); + + APOInitSystemEffects* initStruct = (APOInitSystemEffects*)pbyData; + + PROPVARIANT var; + PropVariantInit(&var); + HRESULT hr = initStruct->pAPOEndpointProperties->GetValue(PKEY_AudioEndpoint_GUID, &var); + if(FAILED(hr)) + { + LogF(L"Can't read endpoint guid"); + return hr; + } + TraceF(L"Endpoint GUID: %s", var.pwszVal); + + wstring apoGuid; + try + { + apoGuid = RegistryHelper::readValue(APP_REGPATH L"\\Child APOs", var.pwszVal); + } + catch(RegistryException e) + { + LogF(L"Can't read child apo guid because of: %s", e.getMessage()); + return E_NOTFOUND; + } + + TraceF(L"Child APO GUID: %s", apoGuid.c_str()); + + GUID childGuid; + hr = CLSIDFromString(apoGuid.c_str(), &childGuid); + if(FAILED(hr)) + { + LogF(L"Can't convert guid string to guid"); + return hr; + } + + hr = CoCreateInstance(childGuid, NULL, CLSCTX_INPROC_SERVER, __uuidof(IAudioProcessingObject), (void**)&childAPO); + if(FAILED(hr)) + { + LogF(L"Error in CoCreateInstance for child apo"); + resetChild(); + return hr; + } + + hr = childAPO->QueryInterface(__uuidof(IAudioProcessingObjectRT), (void**)&childRT); + if(FAILED(hr)) + { + LogF(L"Error in QueryInterface for child apo RT"); + resetChild(); + return hr; + } + + hr = childAPO->QueryInterface(__uuidof(IAudioProcessingObjectConfiguration), (void**)&childCfg); + if(FAILED(hr)) + { + LogF(L"Error in QueryInterface for child apo configuration"); + resetChild(); + return hr; + } + + hr = childAPO->Initialize(cbDataSize, pbyData); + if(FAILED(hr)) + { + LogF(L"Error in Initialize of child apo"); + resetChild(); + return hr; + } + + TraceF(L"Successfully created and initialized child APO"); + return hr; +} + +HRESULT EqualizerAPO::IsInputFormatSupported(IAudioMediaType* pOutputFormat, + IAudioMediaType* pRequestedInputFormat, IAudioMediaType** ppSupportedInputFormat) +{ + if(!pRequestedInputFormat) + return E_POINTER; + + UNCOMPRESSEDAUDIOFORMAT inFormat; + HRESULT hr = pRequestedInputFormat->GetUncompressedAudioFormat(&inFormat); + if(FAILED(hr)) + { + LogF(L"Error in GetUncompressedAudioFormat"); + return hr; + } + + TraceF(L"RequestedInputFormat = { %08X, %u, %u, %u, %f, %08X }", + inFormat.guidFormatType.Data1, inFormat.dwSamplesPerFrame, inFormat.dwBytesPerSampleContainer, + inFormat.dwValidBitsPerSample, inFormat.fFramesPerSecond, inFormat.dwChannelMask); + + if(childAPO) + { + hr = childAPO->IsInputFormatSupported(pOutputFormat, pRequestedInputFormat, ppSupportedInputFormat); + if(SUCCEEDED(hr)) + { + TraceF(L"Success in IsInputFormatSupported of child apo"); + return hr; + } + else + { + LogF(L"Failure in IsInputFormatSupported of child apo"); + resetChild(); + } + } + + return CBaseAudioProcessingObject::IsInputFormatSupported(pOutputFormat, pRequestedInputFormat, ppSupportedInputFormat); +} + +void EqualizerAPO::APOProcess(UINT32 u32NumInputConnections, + APO_CONNECTION_PROPERTY** ppInputConnections, UINT32 u32NumOutputConnections, + APO_CONNECTION_PROPERTY** ppOutputConnections) +{ + switch( ppInputConnections[0]->u32BufferFlags ) + { + case BUFFER_VALID: + { + float* inputFrames = reinterpret_cast(ppInputConnections[0]->pBuffer); + float* outputFrames = reinterpret_cast(ppOutputConnections[0]->pBuffer); + + if(childRT) + { + childRT->APOProcess(u32NumInputConnections, ppInputConnections, u32NumOutputConnections, ppOutputConnections); + + peq.process(outputFrames, outputFrames, ppInputConnections[0]->u32ValidFrameCount); + } + else + peq.process(outputFrames, inputFrames, ppInputConnections[0]->u32ValidFrameCount); + + ppOutputConnections[0]->u32ValidFrameCount = ppInputConnections[0]->u32ValidFrameCount; + ppOutputConnections[0]->u32BufferFlags = ppInputConnections[0]->u32BufferFlags; + + break; + } + case BUFFER_SILENT: + { + ppOutputConnections[0]->u32ValidFrameCount = ppInputConnections[0]->u32ValidFrameCount; + ppOutputConnections[0]->u32BufferFlags = ppInputConnections[0]->u32BufferFlags; + + break; + } + } +} + +HRESULT EqualizerAPO::LockForProcess(UINT32 u32NumInputConnections, + APO_CONNECTION_DESCRIPTOR** ppInputConnections, UINT32 u32NumOutputConnections, + APO_CONNECTION_DESCRIPTOR** ppOutputConnections) +{ + HRESULT hr; + if(childCfg != NULL) + { + hr = childCfg->LockForProcess(u32NumInputConnections, ppInputConnections, u32NumOutputConnections, + ppOutputConnections); + if(SUCCEEDED(hr)) + TraceF(L"Success in LockForProcess of child apo"); + } + + hr = CBaseAudioProcessingObject::LockForProcess(u32NumInputConnections, ppInputConnections, + u32NumOutputConnections, ppOutputConnections); + if(FAILED(hr)) + { + LogF(L"Error in CBaseAudioProcessingObject::LockForProcess"); + return hr; + } + + UNCOMPRESSEDAUDIOFORMAT uncompAudioFormat; + hr = ppOutputConnections[0]->pFormat->GetUncompressedAudioFormat(&uncompAudioFormat); + if(FAILED(hr)) + { + LogF(L"Error in GetUncompressedAudioFormat in LockForProcess"); + return hr; + } + + peq.initialize(uncompAudioFormat.fFramesPerSecond, uncompAudioFormat.dwSamplesPerFrame); + + return hr; +} + +HRESULT EqualizerAPO::UnlockForProcess() +{ + if(childCfg) + { + HRESULT hr = childCfg->UnlockForProcess(); + if(FAILED(hr)) + { + LogF(L"Error in UnlockForProcess"); + return hr; + } + } + + return CBaseAudioProcessingObject::UnlockForProcess(); +} + +void EqualizerAPO::resetChild() +{ + if(childAPO != NULL) + { + childAPO->Release(); + childAPO = NULL; + } + + if(childRT != NULL) + { + childRT->Release(); + childRT = NULL; + } + + if(childCfg != NULL) + { + childCfg->Release(); + childCfg = NULL; + } +} + +HRESULT EqualizerAPO::NonDelegatingQueryInterface(const IID& iid, void** ppv) +{ + if(iid == __uuidof(IUnknown)) + *ppv = static_cast(this); + else if(iid == __uuidof(IAudioProcessingObject)) + *ppv = static_cast(this); + else if(iid == __uuidof(IAudioProcessingObjectRT)) + *ppv = static_cast(this); + else if(iid == __uuidof(IAudioProcessingObjectConfiguration)) + *ppv = static_cast(this); + else if(iid == __uuidof(IAudioSystemEffects)) + *ppv = static_cast(this); + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + + reinterpret_cast(*ppv)->AddRef(); + return S_OK; +} + +ULONG EqualizerAPO::NonDelegatingAddRef() +{ + return InterlockedIncrement(&refCount); +} + +ULONG EqualizerAPO::NonDelegatingRelease() +{ + if(InterlockedDecrement(&refCount) == 0) + { + delete this; + return 0; + } + + return refCount; +} diff --git a/EqualizerAPO.def b/EqualizerAPO.def new file mode 100644 index 0000000..3a3e292 --- /dev/null +++ b/EqualizerAPO.def @@ -0,0 +1,5 @@ +EXPORTS + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE diff --git a/EqualizerAPO.h b/EqualizerAPO.h new file mode 100644 index 0000000..4539fb6 --- /dev/null +++ b/EqualizerAPO.h @@ -0,0 +1,81 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#pragma once + +#include +#include +#include +#include "ParametricEQ.h" + +class INonDelegatingUnknown +{ + virtual HRESULT __stdcall NonDelegatingQueryInterface(const IID& iid, void** ppv) = 0; + virtual ULONG __stdcall NonDelegatingAddRef() = 0; + virtual ULONG __stdcall NonDelegatingRelease() = 0; +}; + +class __declspec(uuid("{EC1CC9CE-FAED-4822-828A-82A81A6F018F}")) EqualizerAPO + : public CBaseAudioProcessingObject, public IAudioSystemEffects, public INonDelegatingUnknown +{ +public: + EqualizerAPO(IUnknown* pUnkOuter); + virtual ~EqualizerAPO(); + + // IUnknown + virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv); + virtual ULONG __stdcall AddRef(); + virtual ULONG __stdcall Release(); + + // IAudioProcessingObject + virtual HRESULT __stdcall GetLatency(HNSTIME* pTime); + virtual HRESULT __stdcall Initialize(UINT32 cbDataSize, BYTE* pbyData); + virtual HRESULT __stdcall IsInputFormatSupported(IAudioMediaType* pOutputFormat, + IAudioMediaType* pRequestedInputFormat, IAudioMediaType** ppSupportedInputFormat); + + // IAudioProcessingObjectRT + virtual void __stdcall APOProcess(UINT32 u32NumInputConnections, + APO_CONNECTION_PROPERTY** ppInputConnections, UINT32 u32NumOutputConnections, + APO_CONNECTION_PROPERTY** ppOutputConnections); + + // IAudioProcessingObjectConfiguration + virtual HRESULT __stdcall LockForProcess(UINT32 u32NumInputConnections, + APO_CONNECTION_DESCRIPTOR** ppInputConnections, UINT32 u32NumOutputConnections, + APO_CONNECTION_DESCRIPTOR** ppOutputConnections); + virtual HRESULT __stdcall UnlockForProcess(void); + + // INonDelegatingUnknown + virtual HRESULT __stdcall NonDelegatingQueryInterface(const IID& iid, void** ppv); + virtual ULONG __stdcall NonDelegatingAddRef(); + virtual ULONG __stdcall NonDelegatingRelease(); + + static long instCount; + static const CRegAPOProperties<1> regProperties; + +private: + long refCount; + IUnknown* pUnkOuter; + ParametricEQ peq; + + void resetChild(); + + IAudioProcessingObject* childAPO; + IAudioProcessingObjectRT* childRT; + IAudioProcessingObjectConfiguration* childCfg; +}; diff --git a/EqualizerAPO.rc b/EqualizerAPO.rc new file mode 100644 index 0000000..729f6ef Binary files /dev/null and b/EqualizerAPO.rc differ diff --git a/EqualizerAPO.sln b/EqualizerAPO.sln new file mode 100644 index 0000000..40bd2fa --- /dev/null +++ b/EqualizerAPO.sln @@ -0,0 +1,49 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EqualizerAPO", "EqualizerAPO.vcxproj", "{5AF4EE2B-CC80-4AE5-A786-86FACC0CC649}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Configurator", "Configurator\Configurator.vcxproj", "{E18E1CA7-3D6C-4CD5-9CE9-E72565A206E5}" + ProjectSection(ProjectDependencies) = postProject + {5AF4EE2B-CC80-4AE5-A786-86FACC0CC649} = {5AF4EE2B-CC80-4AE5-A786-86FACC0CC649} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Benchmark", "Benchmark\Benchmark.vcxproj", "{D4474852-5724-4253-95C6-7A6DC424F194}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5AF4EE2B-CC80-4AE5-A786-86FACC0CC649}.Debug|Win32.ActiveCfg = Debug|Win32 + {5AF4EE2B-CC80-4AE5-A786-86FACC0CC649}.Debug|Win32.Build.0 = Debug|Win32 + {5AF4EE2B-CC80-4AE5-A786-86FACC0CC649}.Debug|x64.ActiveCfg = Debug|x64 + {5AF4EE2B-CC80-4AE5-A786-86FACC0CC649}.Debug|x64.Build.0 = Debug|x64 + {5AF4EE2B-CC80-4AE5-A786-86FACC0CC649}.Release|Win32.ActiveCfg = Release|Win32 + {5AF4EE2B-CC80-4AE5-A786-86FACC0CC649}.Release|Win32.Build.0 = Release|Win32 + {5AF4EE2B-CC80-4AE5-A786-86FACC0CC649}.Release|x64.ActiveCfg = Release|x64 + {5AF4EE2B-CC80-4AE5-A786-86FACC0CC649}.Release|x64.Build.0 = Release|x64 + {E18E1CA7-3D6C-4CD5-9CE9-E72565A206E5}.Debug|Win32.ActiveCfg = Debug|Win32 + {E18E1CA7-3D6C-4CD5-9CE9-E72565A206E5}.Debug|Win32.Build.0 = Debug|Win32 + {E18E1CA7-3D6C-4CD5-9CE9-E72565A206E5}.Debug|x64.ActiveCfg = Debug|x64 + {E18E1CA7-3D6C-4CD5-9CE9-E72565A206E5}.Debug|x64.Build.0 = Debug|x64 + {E18E1CA7-3D6C-4CD5-9CE9-E72565A206E5}.Release|Win32.ActiveCfg = Release|Win32 + {E18E1CA7-3D6C-4CD5-9CE9-E72565A206E5}.Release|Win32.Build.0 = Release|Win32 + {E18E1CA7-3D6C-4CD5-9CE9-E72565A206E5}.Release|x64.ActiveCfg = Release|x64 + {E18E1CA7-3D6C-4CD5-9CE9-E72565A206E5}.Release|x64.Build.0 = Release|x64 + {D4474852-5724-4253-95C6-7A6DC424F194}.Debug|Win32.ActiveCfg = Debug|Win32 + {D4474852-5724-4253-95C6-7A6DC424F194}.Debug|Win32.Build.0 = Debug|Win32 + {D4474852-5724-4253-95C6-7A6DC424F194}.Debug|x64.ActiveCfg = Debug|x64 + {D4474852-5724-4253-95C6-7A6DC424F194}.Debug|x64.Build.0 = Debug|x64 + {D4474852-5724-4253-95C6-7A6DC424F194}.Release|Win32.ActiveCfg = Release|Win32 + {D4474852-5724-4253-95C6-7A6DC424F194}.Release|Win32.Build.0 = Release|Win32 + {D4474852-5724-4253-95C6-7A6DC424F194}.Release|x64.ActiveCfg = Release|x64 + {D4474852-5724-4253-95C6-7A6DC424F194}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/EqualizerAPO.vcxproj b/EqualizerAPO.vcxproj new file mode 100644 index 0000000..747f8e1 --- /dev/null +++ b/EqualizerAPO.vcxproj @@ -0,0 +1,190 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {5AF4EE2B-CC80-4AE5-A786-86FACC0CC649} + Win32Proj + EqualizerAPO + + + + DynamicLibrary + true + Unicode + false + + + DynamicLibrary + true + Unicode + false + + + DynamicLibrary + false + true + Unicode + + + DynamicLibrary + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(IncludePath);$(DDK_PATH)\inc\api + $(LibraryPath);$(DDK_PATH)\lib\win7\i386 + + + true + $(IncludePath);$(DDK_PATH)\inc\api + $(LibraryPath);$(DDK_PATH)\lib\win7\amd64 + + + false + $(IncludePath);$(DDK_PATH)\inc\api + $(LibraryPath);$(DDK_PATH)\lib\win7\i386 + + + false + $(IncludePath);$(DDK_PATH)\inc\api + $(LibraryPath);$(DDK_PATH)\lib\win7\amd64 + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;EQUALIZERAPO_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + wmcodecdspuuid.lib;AudioBaseProcessingObject.lib;audiomediatypecrt.lib;Shlwapi.lib;%(AdditionalDependencies) + EqualizerAPO.def + + + $(ProjectName).tlb + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;EQUALIZERAPO_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + wmcodecdspuuid.lib;AudioBaseProcessingObject.lib;audiomediatypecrt.lib;Shlwapi.lib;%(AdditionalDependencies) + EqualizerAPO.def + + + $(ProjectName).tlb + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;EQUALIZERAPO_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + true + true + wmcodecdspuuid.lib;AudioBaseProcessingObject.lib;audiomediatypecrt.lib;Shlwapi.lib;%(AdditionalDependencies) + EqualizerAPO.def + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;EQUALIZERAPO_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + true + true + wmcodecdspuuid.lib;AudioBaseProcessingObject.lib;audiomediatypecrt.lib;Shlwapi.lib;%(AdditionalDependencies) + EqualizerAPO.def + + + + + + + + + + + + + + + + + + + + + + + + + true + true + + + true + true + + + + + + \ No newline at end of file diff --git a/EqualizerAPO64.rc b/EqualizerAPO64.rc new file mode 100644 index 0000000..3a11b3b Binary files /dev/null and b/EqualizerAPO64.rc differ diff --git a/License.txt b/License.txt new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/License.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/LogHelper.cpp b/LogHelper.cpp new file mode 100644 index 0000000..fa7e48e --- /dev/null +++ b/LogHelper.cpp @@ -0,0 +1,88 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#define WIN32_LEAN_AND_MEAN +#include + +#include "RegistryHelper.h" +#include "LogHelper.h" + +using namespace std; + +bool LogHelper::initialized = false; +wstring LogHelper::logPath; +bool LogHelper::enableTrace = false; + +void LogHelper::log(const char* file, int line, void* caller, bool trace, const wchar_t* format, ...) +{ + if(!initialized) + { + //Do not try to initialize again, even in case of error + initialized = true; + + wchar_t temp[255]; + GetTempPathW(sizeof(temp)/sizeof(wchar_t), temp); + + logPath = temp; + logPath += L"EqualizerAPO.log"; + + try + { + if(RegistryHelper::readValue(APP_REGPATH, L"EnableTrace") != L"false") + enableTrace = true; + } + catch(RegistryException e) + { + LogFStatic(L"%s", e.getMessage()); + } + } + + if(trace && !enableTrace) + return; + + FILE* fp; + errno_t err = _wfopen_s(&fp, logPath.c_str(), L"at"); + if(err != 0) + return; + + SYSTEMTIME ___st; + GetLocalTime(&___st); + fwprintf(fp, L"%04d-%02d-%02d %02d:%02d:%02d.%03d %08X (%S:%d): ", + ___st.wYear, ___st.wMonth, ___st.wDay, ___st.wHour, ___st.wMinute, ___st.wSecond, ___st.wMilliseconds, caller, file, line); + + if(trace) + fwprintf(fp, L"(TRACE) "); + + va_list varArgs; + va_start(varArgs, format); + vfwprintf(fp, format, varArgs); + va_end(varArgs); + + fwprintf(fp, L"\n"); + fclose(fp); +} + +void LogHelper::reset() +{ + initialized = false; + logPath = L""; + enableTrace = false; +} diff --git a/LogHelper.h b/LogHelper.h new file mode 100644 index 0000000..fc534fa --- /dev/null +++ b/LogHelper.h @@ -0,0 +1,39 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#pragma once + +#include + +#define TraceF(format, ...) LogHelper::log(__FILE__, __LINE__, this, true, format, __VA_ARGS__); +#define TraceFStatic(format, ...) LogHelper::log(__FILE__, __LINE__, NULL, true, format, __VA_ARGS__); +#define LogF(format, ...) LogHelper::log(__FILE__, __LINE__, this, false, format, __VA_ARGS__); +#define LogFStatic(format, ...) LogHelper::log(__FILE__, __LINE__, NULL, false, format, __VA_ARGS__); + +class LogHelper +{ +public: + static void log(const char* file, int line, void* caller, bool trace, const wchar_t* format, ...); + static void reset(); + +private: + static bool initialized; + static std::wstring logPath; + static bool enableTrace; +}; diff --git a/ParametricEQ.cpp b/ParametricEQ.cpp new file mode 100644 index 0000000..242ecf7 --- /dev/null +++ b/ParametricEQ.cpp @@ -0,0 +1,338 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#define _USE_MATH_DEFINES +#include +#include +#include +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include "RegistryHelper.h" +#include "LogHelper.h" +#include "ParametricEQ.h" + +using namespace std; + +BiQuad::BiQuad(float dbGain, float freq, float srate, float bandwidthOrQ, bool isQ) +{ + float A = pow(10, dbGain / 40); + float omega = 2 * (float)M_PI * freq / srate; + float sn = sin(omega); + float cs = cos(omega); + float alpha; + if(isQ) + alpha = sn / (2 * bandwidthOrQ); + else + alpha = sn * sinh((float)M_LN2/2 * bandwidthOrQ * omega / sn); + + float temp = 1 + (alpha /A); + a0 = (1 + (alpha * A)) / temp; + a[0] = (-2 * cs) / temp; + a[1] = (1 - (alpha * A)) / temp; + a[2] = - (-2 * cs) / temp; + a[3] = - (1 - (alpha /A)) / temp; +} + +ParametricEQ::ParametricEQ() +{ + filterCount = 0; + channelCount = 0; + preamp = 1.0f; + memset(sampleData, 0, 1000 * sizeof(float)); + lastInputWasSilent = false; + threadHandle = NULL; +} + +ParametricEQ::~ParametricEQ() +{ + if(threadHandle != NULL) + { + SetEvent(shutdownEvent); + if(WaitForSingleObject(threadHandle, INFINITE) == WAIT_OBJECT_0) + { + TraceF(L"Successfully terminated directory change notification thread", configPath.c_str()); + } + CloseHandle(shutdownEvent); + CloseHandle(threadHandle); + threadHandle = NULL; + } +} + +void ParametricEQ::initialize(float sampleRate, unsigned channelCount) +{ + this->sampleRate = sampleRate; + this->channelCount = channelCount; + memset(sampleData, 0, 1000 * sizeof(float)); + filterCount = 0; + preamp = 1.0f; + + try + { + configPath = RegistryHelper::readValue(APP_REGPATH, L"ConfigPath"); + } + catch(RegistryException e) + { + LogF(L"Can't read config path because of: %s", e.getMessage()); + return; + } + if(configPath != L"") + { + loadConfig(); + + if(threadHandle == NULL) + { + shutdownEvent = CreateEventW(NULL, true, false, NULL); + threadHandle = CreateThread(NULL, 0, notificationThread, this, 0, NULL); + if(threadHandle == INVALID_HANDLE_VALUE) + threadHandle = NULL; + else + { + TraceF(L"Successfully created directory change notification thread for %s and its subtree", configPath.c_str()); + } + } + } +} + +void ParametricEQ::loadConfig() +{ + unsigned loadFilterCount = 0; + float loadPreamp = 1.0f; + + loadConfig(configPath + L"\\config.txt", loadFilterCount, loadPreamp); + + TraceF(L"%d filters loaded", loadFilterCount); + preamp = loadPreamp; + filterCount = loadFilterCount; +} + +void ParametricEQ::loadConfig(wstring path, unsigned& loadFilterCount, float& loadPreamp) +{ + TraceF(L"Loading configuration from %s", path.c_str()); + + ifstream inputStream(path); + if(!inputStream.good()) + { + LogF(L"Config file not found at %s!", path.c_str()); + return; + } + + while(!inputStream.eof()) + { + string line; + getline(inputStream, line); + + size_t pos = line.find(':'); + if(pos != -1) + { + string key = line.substr(0, pos); + string value = line.substr(pos + 1); + + //Conversion to period as decimal mark, if needed + for(unsigned i=0;i 0 && iswspace(value[0])) + value = value.substr(1); + + int length = MultiByteToWideChar(CP_UTF8, 0, value.c_str(), -1, NULL, 0); + wchar_t* charBuf = new wchar_t[length]; + MultiByteToWideChar(CP_UTF8, 0, value.c_str(), -1, charBuf, length); + + wstring includePath; + if(PathIsRelativeA(value.c_str())) + { + wchar_t filePath[MAX_PATH]; + path._Copy_s(filePath, sizeof(filePath), MAX_PATH); + if(path.size() < MAX_PATH) + filePath[path.size()]=L'\0'; + else + filePath[MAX_PATH - 1]=L'\0'; + PathRemoveFileSpecW(filePath); + PathAppendW(filePath, charBuf); + includePath = filePath; + } + else + includePath = charBuf; + + delete charBuf; + + loadConfig(includePath, loadFilterCount, loadPreamp); + } + } + } +} + +#define IS_DENORMAL(f) (((*(unsigned int *)&(f))&0x7f800000) == 0) + +void ParametricEQ::process(float *output, float *input, unsigned frameCount) +{ + bool inputSilent = true; + + for (unsigned i = 0; i < frameCount * channelCount; i++) + { + if(input[i] != 0) + { + inputSilent = false; + break; + } + } + + if(inputSilent) + { + if(lastInputWasSilent) + { + //Avoid processing cost if silence would be output anyway + if(input != output) + memset(output, 0, frameCount * channelCount * sizeof(float)); + + return; + } + else + lastInputWasSilent = true; + } + else + lastInputWasSilent = false; + + //Avoid denormals + for(unsigned i = 0; i < (filterCount+1)*channelCount*2; i++) + if(IS_DENORMAL(sampleData[i])) + sampleData[i] = 0; + + for (unsigned i = 0; i < frameCount * channelCount; i+=channelCount) + for (unsigned c=0; c= 5) + { + if(freqString[len - 4] == '.') + { + //Interpret as thousands separator because of Room EQ Wizard + result *= 1000.0f; + } + } + + return result; + } + else + return -1.0f; +} + +unsigned long __stdcall ParametricEQ::notificationThread(void* parameter) +{ + ParametricEQ* peq = (ParametricEQ*)parameter; + + HANDLE notificationHandle = FindFirstChangeNotificationW(peq->configPath.c_str(), true, FILE_NOTIFY_CHANGE_LAST_WRITE); + if(notificationHandle == INVALID_HANDLE_VALUE) + notificationHandle = NULL; + + HANDLE handles[2] = {peq->shutdownEvent, notificationHandle}; + while(true) + { + DWORD which = WaitForMultipleObjects(2, handles, false, INFINITE); + + if(which == WAIT_OBJECT_0) + { + //Shutdown + break; + } + else + { + FindNextChangeNotification(notificationHandle); + //Wait for second event within 100 milliseconds to avoid loading twice + WaitForMultipleObjects(1, ¬ificationHandle, false, 100); + peq->loadConfig(); + FindNextChangeNotification(notificationHandle); + } + } + + FindCloseChangeNotification(notificationHandle); + + return 0; +} diff --git a/ParametricEQ.h b/ParametricEQ.h new file mode 100644 index 0000000..800b4c5 --- /dev/null +++ b/ParametricEQ.h @@ -0,0 +1,58 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#pragma once + +#include + +struct BiQuad +{ + BiQuad() {} + BiQuad(float dbGain, float freq, float srate, float bandwidthOrQ, bool isQ); + + __declspec(align(16)) float a[4]; + float a0; +}; + +class ParametricEQ +{ +public: + ParametricEQ(); + ~ParametricEQ(); + + void initialize(float sampleRate, unsigned channelCount); + void loadConfig(); + void process(float *output, float *input, unsigned frameCount); + +private: + void loadConfig(std::wstring path, unsigned& loadFilterCount, float& loadPreamp); + float getFreq(char* freqString); + static unsigned long __stdcall notificationThread(void* parameter); + + std::wstring configPath; + float sampleRate; + unsigned channelCount; + float preamp; + BiQuad filters[100]; + unsigned filterCount; + float sampleData[2000]; + bool lastInputWasSilent; + void* threadHandle; + void* shutdownEvent; +}; diff --git a/RegistryHelper.cpp b/RegistryHelper.cpp new file mode 100644 index 0000000..14df2f8 --- /dev/null +++ b/RegistryHelper.cpp @@ -0,0 +1,227 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include "RegistryHelper.h" + +using namespace std; + +wstring RegistryHelper::readValue(wstring key, wstring valuename) +{ + wstring result; + + LSTATUS status; + HKEY keyHandle; + status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &keyHandle); + if(status != ERROR_SUCCESS) + throw RegistryException(L"Error while opening registry key HKEY_LOCAL_MACHINE\\" + key + L": " + getSystemErrorString(status)); + + DWORD type; + DWORD bufSize; + status = RegQueryValueExW(keyHandle, valuename.c_str(), NULL, &type, NULL, &bufSize); + if(status != ERROR_SUCCESS) + { + RegCloseKey(keyHandle); + throw RegistryException(L"Error while reading registry value HKEY_LOCAL_MACHINE\\" + key + L"\\" + valuename + L": " + getSystemErrorString(status)); + } + + if(type != REG_SZ) + { + RegCloseKey(keyHandle); + throw RegistryException(L"Registry value HKEY_LOCAL_MACHINE\\" + key + L"\\" + valuename + L" has wrong type"); + } + + wchar_t* buf = new wchar_t[bufSize / sizeof(wchar_t) + 1]; + status = RegQueryValueExW(keyHandle, valuename.c_str(), NULL, NULL, (LPBYTE)buf, &bufSize); + + RegCloseKey(keyHandle); + + if(status != ERROR_SUCCESS) + { + delete buf; + throw RegistryException(L"Error while reading registry value HKEY_LOCAL_MACHINE\\" + key + L"\\" + valuename + L": " + getSystemErrorString(status)); + } + + //Remove zero-termination + if(buf[bufSize / sizeof(wchar_t) - 1] == L'\0') + bufSize -= sizeof(wchar_t); + result = wstring((wchar_t*)buf, (wstring::size_type)bufSize/sizeof(wchar_t)); + delete buf; + + return result; +} + +void RegistryHelper::writeValue(wstring key, wstring valuename, wstring value) +{ + LSTATUS status; + HKEY keyHandle; + status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_SET_VALUE | KEY_WOW64_64KEY, &keyHandle); + if(status != ERROR_SUCCESS) + throw RegistryException(L"Error while opening registry key HKEY_LOCAL_MACHINE\\" + key + L": " + getSystemErrorString(status)); + + status = RegSetValueExW(keyHandle, valuename.c_str(), 0, REG_SZ, (const BYTE*)value.c_str(), (DWORD)((value.size()+1)*sizeof(wchar_t))); + + RegCloseKey(keyHandle); + + if(status != ERROR_SUCCESS) + throw RegistryException(L"Error while writing to registry value HKEY_LOCAL_MACHINE\\" + key + L"\\" + valuename + L": " + getSystemErrorString(status)); +} + +void RegistryHelper::deleteValue(wstring key, wstring valuename) +{ + LSTATUS status; + HKEY keyHandle; + status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_SET_VALUE | KEY_WOW64_64KEY, &keyHandle); + if(status != ERROR_SUCCESS) + throw RegistryException(L"Error while opening registry key HKEY_LOCAL_MACHINE\\" + key + L": " + getSystemErrorString(status)); + + status = RegDeleteValueW(keyHandle, valuename.c_str()); + + RegCloseKey(keyHandle); + + if(status != ERROR_SUCCESS) + throw RegistryException(L"Error while deleting registry value HKEY_LOCAL_MACHINE\\" + key + L"\\" + valuename + L": " + getSystemErrorString(status)); +} + +void RegistryHelper::createKey(wstring key) +{ + HKEY keyHandle; + LSTATUS status; + status = RegCreateKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, NULL, 0, KEY_SET_VALUE | KEY_WOW64_64KEY, NULL, &keyHandle, NULL); + if(status != ERROR_SUCCESS) + throw RegistryException(L"Error while creating registry key HKEY_LOCAL_MACHINE\\" + key + L": " + getSystemErrorString(status)); + + RegCloseKey(keyHandle); +} + +void RegistryHelper::deleteKey(wstring key) +{ + LSTATUS status; + status = RegDeleteKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), KEY_WOW64_64KEY, 0); + if(status != ERROR_SUCCESS) + throw RegistryException(L"Error while deleting registry key HKEY_LOCAL_MACHINE\\" + key + L": " + getSystemErrorString(status)); +} + +bool RegistryHelper::keyExists(wstring key) +{ + bool result; + + HKEY keyHandle; + result = (RegOpenKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &keyHandle) == ERROR_SUCCESS); + + if(result) + RegCloseKey(keyHandle); + + return result; +} + +vector RegistryHelper::enumSubKeys(wstring key) +{ + vector result; + + LSTATUS status; + HKEY keyHandle; + status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY, &keyHandle); + if(status != ERROR_SUCCESS) + throw RegistryException(L"Error while opening registry key HKEY_LOCAL_MACHINE\\" + key + L": " + getSystemErrorString(status)); + + wchar_t keyName[256]; + DWORD keyLength = sizeof(keyName) / sizeof(wchar_t); + int i=0; + int itemCount=0; + + while((status = RegEnumKeyExW(keyHandle, i++, keyName, &keyLength, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS) + { + keyLength = sizeof(keyName) / sizeof(wchar_t); + + result.push_back(keyName); + } + + RegCloseKey(keyHandle); + + if(status != ERROR_NO_MORE_ITEMS) + throw RegistryException(L"Error while enumerating sub keys of registry key HKEY_LOCAL_MACHINE\\" + key + L": " + getSystemErrorString(status)); + + return result; +} + +unsigned long RegistryHelper::valueCount(wstring key) +{ + LSTATUS status; + HKEY keyHandle; + status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &keyHandle); + if(status != ERROR_SUCCESS) + throw RegistryException(L"Error while opening registry key HKEY_LOCAL_MACHINE\\" + key + L": " + getSystemErrorString(status)); + + DWORD valueCount; + status = RegQueryInfoKeyW(keyHandle, NULL, NULL, NULL, NULL, NULL, NULL, &valueCount, NULL, NULL, NULL, NULL); + + RegCloseKey(keyHandle); + + if(status != ERROR_SUCCESS) + throw RegistryException(L"Error while reading info for registry key HKEY_LOCAL_MACHINE\\" + key + L": " + getSystemErrorString(status)); + + return valueCount; +} + +void RegistryHelper::saveToFile(wstring key, wstring valuename, wstring filepath) +{ + wstring value = readValue(key, valuename); + + wofstream stream(filepath); + if(!stream.good()) + throw RegistryException(L"Error while opening file " + filepath + L" for writing"); + + stream << L"Windows Registry Editor Version 5.00\n" << endl; + stream << L"[HKEY_LOCAL_MACHINE\\" << key << L"]" << endl; + stream << L"\"" << valuename << L"\"=\"" << value << L"\"" << endl; + stream << endl; + + stream.close(); +} + +wstring RegistryHelper::getGuidString(GUID guid) +{ + wchar_t* temp; + if(FAILED(StringFromCLSID(guid, &temp))) + throw RegistryException(L"Could not convert GUID to string"); + std::wstring result(temp); + CoTaskMemFree(temp); + + return result; +} + +wstring RegistryHelper::getSystemErrorString(long status) +{ + wchar_t* buf; + + if(FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, status, 0, (LPTSTR)&buf, 0, NULL) != 0) + { + wstring result(buf); + LocalFree(buf); + + return result; + } + else + return L""; +} diff --git a/RegistryHelper.h b/RegistryHelper.h new file mode 100644 index 0000000..64f2094 --- /dev/null +++ b/RegistryHelper.h @@ -0,0 +1,58 @@ +/* + This file is part of EqualizerAPO, a system-wide equalizer. + Copyright (C) 2012 Jonas Thedering + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#pragma once + +#include +#include +#include + +#define APP_REGPATH L"SOFTWARE\\EqualizerAPO" + +class RegistryHelper +{ +public: + static std::wstring readValue(std::wstring key, std::wstring valuename); + static void writeValue(std::wstring key, std::wstring valuename, std::wstring value); + static void deleteValue(std::wstring key, std::wstring valuename); + static void createKey(std::wstring key); + static void deleteKey(std::wstring key); + static std::vector enumSubKeys(std::wstring key); + static bool keyExists(std::wstring key); + static unsigned long valueCount(std::wstring key); + static void saveToFile(std::wstring key, std::wstring valuename, std::wstring filepath); + static std::wstring getGuidString(GUID guid); + +private: + static std::wstring getSystemErrorString(long status); +}; + +class RegistryException +{ +public: + RegistryException(const std::wstring& message):message(message) {} + + std::wstring getMessage() + { + return message; + } + +private: + std::wstring message; +}; diff --git a/Setup/Setup.nsi b/Setup/Setup.nsi new file mode 100644 index 0000000..230f04d --- /dev/null +++ b/Setup/Setup.nsi @@ -0,0 +1,124 @@ +!include "MUI2.nsh" + +!searchparse /file ..\version.h `#define MAJOR ` MAJOR +!searchparse /file ..\version.h `#define MINOR ` MINOR + +!define REGPATH "Software\EqualizerAPO" + +;-------------------------------- +;General + + ;Name and file + Name "Equalizer APO ${MAJOR}.${MINOR}" + + ;Default installation folder + InstallDir "$PROGRAMFILES64\EqualizerAPO" + + ;Request application privileges for Windows Vista + RequestExecutionLevel admin + +;-------------------------------- +;Interface Settings + + !define MUI_ABORTWARNING + !define MUI_COMPONENTSPAGE_NODESC + +;-------------------------------- +;Pages + + !insertmacro MUI_PAGE_WELCOME + !insertmacro MUI_PAGE_LICENSE ..\License.txt + !insertmacro MUI_PAGE_DIRECTORY + !insertmacro MUI_PAGE_INSTFILES + !insertmacro MUI_PAGE_FINISH + + !insertmacro MUI_UNPAGE_WELCOME + !insertmacro MUI_UNPAGE_CONFIRM + !insertmacro MUI_UNPAGE_COMPONENTS + !insertmacro MUI_UNPAGE_INSTFILES + !insertmacro MUI_UNPAGE_FINISH + +;-------------------------------- +;Languages + + !insertmacro MUI_LANGUAGE "English" + !insertmacro MUI_LANGUAGE "German" + +;-------------------------------- +;Installer Sections + +Section "Install" SecInstall + SetRegView 64 + + SetOutPath "$INSTDIR" + SetRebootFlag true + + File "${BINPATH}\EqualizerAPO.dll" + File "${BINPATH}\Configurator.exe" + File "${BINPATH}\Benchmark.exe" + + File "${LIBPATH}\libsndfile-1.dll" + File "${LIBPATH}\msvcp100.dll" + File "${LIBPATH}\msvcr100.dll" + + CreateDirectory "$INSTDIR\config" + + SetOverwrite off + File /oname=config\config.txt "config\config.txt" + File /oname=config\example.txt "config\example.txt" + SetOverwrite on + + ;Grant write access to the config directory for all users + AccessControl::GrantOnFile "$INSTDIR\config" "(S-1-5-32-545)" "FullAccess" + + WriteRegStr HKLM ${REGPATH} "InstallPath" "$INSTDIR" + WriteRegStr HKLM ${REGPATH} "ConfigPath" "$INSTDIR\config" + WriteRegStr HKLM ${REGPATH} "EnableTrace" "false" + + WriteUninstaller "$INSTDIR\Uninstall.exe" + + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Audio" "DisableProtectedAudioDG" 1 + ;RegDLL doesn't work for 64 bit dlls + ExecWait '"$SYSDIR\regsvr32.exe" /s "$INSTDIR\EqualizerAPO.dll"' + + ExecWait '"$INSTDIR\Configurator.exe" /i' + +SectionEnd + +;-------------------------------- +;Uninstaller Sections + +LangString SecRemoveName ${LANG_ENGLISH} "Remove configurations and registry backups" +LangString SecRemoveName ${LANG_GERMAN} "Konfigurationen und Registrierungsbackups entfernen" + +Section /o un.$(SecRemoveName) + + Delete "$INSTDIR\*.reg" + RMDir /REBOOTOK /r "$INSTDIR\config" + +SectionEnd + +Section "-un.Uninstall" + SetRegView 64 + + ExecWait '"$INSTDIR\Configurator.exe" /u' + + ExecWait '"$SYSDIR\regsvr32.exe" /u /s "$INSTDIR\EqualizerAPO.dll"' + DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\Audio" "DisableProtectedAudioDG" + + Delete /REBOOTOK "$INSTDIR\msvcr100.dll" + Delete /REBOOTOK "$INSTDIR\msvcp100.dll" + Delete "$INSTDIR\libsndfile-1.dll" + + Delete "$INSTDIR\Benchmark.exe" + Delete "$INSTDIR\Configurator.exe" + Delete /REBOOTOK "$INSTDIR\EqualizerAPO.dll" + + Delete "$INSTDIR\Uninstall.exe" + + ;Only remove if empty + RMDir /REBOOTOK "$INSTDIR" + + DeleteRegKey /ifempty HKLM ${REGPATH} + +SectionEnd diff --git a/Setup/Setup32.nsi b/Setup/Setup32.nsi new file mode 100644 index 0000000..cc87874 --- /dev/null +++ b/Setup/Setup32.nsi @@ -0,0 +1,16 @@ + +!define BINPATH "..\Release" +!define LIBPATH "lib32" + +!include "Setup.nsi" + +LangString VersionError ${LANG_ENGLISH} "This installer is only supposed to be run on 32-Bit Windows. Please use the 64-Bit installer." +LangString VersionError ${LANG_GERMAN} "Dieses Installationsprogramm kann nur auf einem 32-Bit-Windows verwendet werden. Bitte nutzen Sie die 64-Bit-Version." + +Function .onInit + StrCmp $PROGRAMFILES32 $PROGRAMFILES64 +3 + MessageBox MB_OK|MB_ICONSTOP $(VersionError) + Abort +FunctionEnd + +OutFile "EqualizerAPO32-${MAJOR}.${MINOR}.exe" diff --git a/Setup/Setup64.nsi b/Setup/Setup64.nsi new file mode 100644 index 0000000..d1d5b62 --- /dev/null +++ b/Setup/Setup64.nsi @@ -0,0 +1,16 @@ + +!define BINPATH "..\x64\Release" +!define LIBPATH "lib64" + +!include "Setup.nsi" + +LangString VersionError ${LANG_ENGLISH} "This installer is only supposed to be run on 64-Bit Windows. Please use the 32-Bit installer." +LangString VersionError ${LANG_GERMAN} "Dieses Installationsprogramm kann nur auf einem 64-Bit-Windows verwendet werden. Bitte nutzen Sie die 32-Bit-Version." + +Function .onInit + StrCmp $PROGRAMFILES32 $PROGRAMFILES64 0 +3 + MessageBox MB_OK|MB_ICONSTOP $(VersionError) + Abort +FunctionEnd + +OutFile "EqualizerAPO64-${MAJOR}.${MINOR}.exe" diff --git a/Setup/config/config.txt b/Setup/config/config.txt new file mode 100644 index 0000000..c95b4d3 --- /dev/null +++ b/Setup/config/config.txt @@ -0,0 +1,2 @@ +Preamp: -6 db +Include: example.txt diff --git a/Setup/config/example.txt b/Setup/config/example.txt new file mode 100644 index 0000000..edd5e48 --- /dev/null +++ b/Setup/config/example.txt @@ -0,0 +1,30 @@ +Filter Settings file + +Room EQ V5,01 +Dated: 29.02.2012 20:04:50 + +Notes:Simple bass boost + +Equaliser: Generic +No measurement +Filter 1: ON PK Fc 20,0 Hz Gain 4,0 dB Q 1,00 +Filter 2: ON PK Fc 45,0 Hz Gain 2,0 dB Q 1,00 +Filter 3: OFF None +Filter 4: OFF None +Filter 5: OFF None +Filter 6: OFF None +Filter 7: OFF None +Filter 8: OFF None +Filter 9: OFF None +Filter 10: OFF None +Filter 11: OFF None +Filter 12: OFF None +Filter 13: OFF None +Filter 14: OFF None +Filter 15: OFF None +Filter 16: OFF None +Filter 17: OFF None +Filter 18: OFF None +Filter 19: OFF None +Filter 20: OFF None + diff --git a/Setup/lib32/libsndfile-1.dll b/Setup/lib32/libsndfile-1.dll new file mode 100644 index 0000000..545ffb5 Binary files /dev/null and b/Setup/lib32/libsndfile-1.dll differ diff --git a/Setup/lib32/msvcp100.dll b/Setup/lib32/msvcp100.dll new file mode 100644 index 0000000..e9eae44 Binary files /dev/null and b/Setup/lib32/msvcp100.dll differ diff --git a/Setup/lib32/msvcr100.dll b/Setup/lib32/msvcr100.dll new file mode 100644 index 0000000..fd91c89 Binary files /dev/null and b/Setup/lib32/msvcr100.dll differ diff --git a/Setup/lib64/libsndfile-1.dll b/Setup/lib64/libsndfile-1.dll new file mode 100644 index 0000000..4cfe69c Binary files /dev/null and b/Setup/lib64/libsndfile-1.dll differ diff --git a/Setup/lib64/msvcp100.dll b/Setup/lib64/msvcp100.dll new file mode 100644 index 0000000..68fa0d3 Binary files /dev/null and b/Setup/lib64/msvcp100.dll differ diff --git a/Setup/lib64/msvcr100.dll b/Setup/lib64/msvcr100.dll new file mode 100644 index 0000000..0318fb0 Binary files /dev/null and b/Setup/lib64/msvcr100.dll differ diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..0ce2d5e --- /dev/null +++ b/build.bat @@ -0,0 +1,8 @@ +call "%VS100COMNTOOLS%\vsvars32.bat" +msbuild EqualizerAPO.sln /p:Configuration=release /p:platform=win32 /t:rebuild +msbuild EqualizerAPO.sln /p:Configuration=release /p:platform=x64 /t:rebuild + +cd Setup +"%ProgramFiles%\NSIS\makensis.exe" Setup32.nsi +"%ProgramFiles%\NSIS\makensis.exe" Setup64.nsi +cd.. diff --git a/resource.h b/resource.h new file mode 100644 index 0000000..98d9578 Binary files /dev/null and b/resource.h differ diff --git a/version.h b/version.h new file mode 100644 index 0000000..91a52cc --- /dev/null +++ b/version.h @@ -0,0 +1,2 @@ +#define MAJOR 0 +#define MINOR 5