From ef61580c192e60218ce185621350326897bf0900 Mon Sep 17 00:00:00 2001
From: jthedering <51533355+jthedering@users.noreply.github.com>
Date: Sun, 3 Feb 2013 12:54:20 +0000
Subject: [PATCH] Added: Support for having individual configurations for
multiple devices. This is possible via the new command "Device" that allows
to select the output devices to which the following commands (filters etc.)
should be applied. The Configurator got a new button to generate a Device
command for the selected connection(s).
---
Benchmark/Benchmark.cpp | 1 +
Benchmark/Benchmark.vcxproj | 2 +
Configurator/Configurator.cpp | 50 ++++++-
Configurator/Configurator.h | 3 +-
Configurator/Configurator.rc | Bin 10696 -> 11470 bytes
Configurator/Configurator.vcxproj | 6 +-
Configurator/resource.h | Bin 2792 -> 2974 bytes
.../DeviceAPOInfo.cpp => DeviceAPOInfo.cpp | 52 ++++---
.../DeviceAPOInfo.h => DeviceAPOInfo.h | 1 +
EqualizerAPO.cpp | 8 +-
EqualizerAPO.vcxproj | 4 +
ParametricEQ.cpp | 132 +++++++++++++-----
ParametricEQ.h | 6 +-
RegistryHelper.cpp | 28 ----
RegistryHelper.h | 1 -
StringHelper.cpp | 56 ++++++++
StringHelper.h | 32 +++++
17 files changed, 290 insertions(+), 92 deletions(-)
rename Configurator/DeviceAPOInfo.cpp => DeviceAPOInfo.cpp (67%)
rename Configurator/DeviceAPOInfo.h => DeviceAPOInfo.h (93%)
create mode 100644 StringHelper.cpp
create mode 100644 StringHelper.h
diff --git a/Benchmark/Benchmark.cpp b/Benchmark/Benchmark.cpp
index 660b059..78e094e 100644
--- a/Benchmark/Benchmark.cpp
+++ b/Benchmark/Benchmark.cpp
@@ -87,6 +87,7 @@ int main(int argc, char** argv)
printf("Processing %d frames from %d channel(s)\n", frameCount, channelCount);
ParametricEQ peq;
+ peq.setDeviceInfo(L"Benchmark", L"File output", L"");
peq.initialize((float)sampleRate, channelCount);
PrecisionTimer timer;
diff --git a/Benchmark/Benchmark.vcxproj b/Benchmark/Benchmark.vcxproj
index e1fcba8..7deb58f 100644
--- a/Benchmark/Benchmark.vcxproj
+++ b/Benchmark/Benchmark.vcxproj
@@ -152,12 +152,14 @@
+
+
diff --git a/Configurator/Configurator.cpp b/Configurator/Configurator.cpp
index 7cf55c6..7beffc7 100644
--- a/Configurator/Configurator.cpp
+++ b/Configurator/Configurator.cpp
@@ -20,6 +20,7 @@
#define WIN32_LEAN_AND_MEAN
#include
#include
+#include "../StringHelper.h"
#include "../RegistryHelper.h"
#include "Configurator.h"
@@ -41,11 +42,15 @@ void Configurator::onInitDialog(HWND hDlg)
okButton = GetDlgItem(hDlg, IDOK);
cancelButton = GetDlgItem(hDlg, IDCANCEL);
requestLabel = GetDlgItem(hDlg, IDC_REQUEST);
+ copyDeviceCommandButton = GetDlgItem(hDlg, IDC_COPY_DEVICE_COMMAND);
wchar_t stringBuf[255];
LoadStringW(hInstance, IDS_REQUEST, stringBuf, sizeof(stringBuf)/sizeof(wchar_t));
SetWindowTextW(requestLabel, stringBuf);
+ LoadStringW(hInstance, IDS_COPY_DEVICE_COMMAND, stringBuf, sizeof(stringBuf)/sizeof(wchar_t));
+ SetWindowTextW(copyDeviceCommandButton, stringBuf);
+
ListView_SetExtendedListViewStyle(deviceList, ListView_GetExtendedListViewStyle(deviceList) | LVS_EX_CHECKBOXES);
LVCOLUMN column;
column.pszText = stringBuf;
@@ -139,6 +144,8 @@ void Configurator::onLvnItemChanged(unsigned sourceId, LPNMLISTVIEW info)
}
EnableWindow(okButton, changed);
+
+ EnableWindow(copyDeviceCommandButton, ListView_GetSelectedCount(deviceList) > 0);
}
}
@@ -168,8 +175,45 @@ void Configurator::onButtonClicked(unsigned sourceId)
MessageBoxW(hDlg, e.getMessage().c_str(), L"Error while accessing the registry", MB_ICONERROR | MB_OK);
}
}
+ else if(sourceId = IDC_COPY_DEVICE_COMMAND)
+ {
+ wstring command = L"Device: ";
- if(cmdLine == L"/i")
+ bool first = true;
+ for(int i = 0; i < ListView_GetItemCount(deviceList); i++)
+ {
+ LVITEM item;
+ item.iItem = i;
+ item.iSubItem = 0;
+ item.mask = LVIF_PARAM | LVIF_STATE;
+ item.stateMask = LVIS_SELECTED;
+ ListView_GetItem(deviceList, &item);
+
+ if(item.state & LVIS_SELECTED)
+ {
+ if(first)
+ first = false;
+ else
+ command += L"; ";
+
+ DeviceAPOInfo info = apoInfos[item.lParam];
+ command += StringHelper::replaceCharacters(info.deviceName + L" " + info.connectionName + L" " + info.deviceGuid, L";", L' ');
+ }
+ }
+
+ OpenClipboard(hDlg);
+
+ HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE, (command.length() + 1) * sizeof(wchar_t));
+ wchar_t* data = (wchar_t*)GlobalLock(hData);
+ memcpy(data, command.c_str(), (command.length() + 1) * sizeof(wchar_t));
+ GlobalUnlock(data);
+
+ SetClipboardData(CF_UNICODETEXT, hData);
+
+ CloseClipboard();
+ }
+
+ if((sourceId == IDOK || sourceId == IDCANCEL) && cmdLine == L"/i")
{
wchar_t stringBuf[255];
LoadStringW(hInstance, IDS_AFTERINSTALL, stringBuf, sizeof(stringBuf)/sizeof(wchar_t));
@@ -229,10 +273,10 @@ INT_PTR CALLBACK dlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
return (INT_PTR)TRUE;
case WM_COMMAND:
+ configurator->onButtonClicked(LOWORD(wParam));
+
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
- configurator->onButtonClicked(LOWORD(wParam));
-
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
diff --git a/Configurator/Configurator.h b/Configurator/Configurator.h
index 5726ab6..5a6c5f0 100644
--- a/Configurator/Configurator.h
+++ b/Configurator/Configurator.h
@@ -22,7 +22,7 @@
#include "resource.h"
#include
#include
-#include "DeviceAPOInfo.h"
+#include "../DeviceAPOInfo.h"
class Configurator
{
@@ -38,6 +38,7 @@ private:
HWND deviceList;
HWND okButton;
HWND cancelButton;
+ HWND copyDeviceCommandButton;
HWND requestLabel;
std::wstring cmdLine;
diff --git a/Configurator/Configurator.rc b/Configurator/Configurator.rc
index b848a8156befb247b7b6d25f852db6d1cec42d7f..70a8074fb8080aaf6cea303329825aae721ae5d6 100644
GIT binary patch
delta 665
zcmX>Rd@gds0=~%=TtfB!3;_(04Dk#u46Y1e44w?mKsp{s`ZM?fp(BGIP)314iNTv8
zpP_&ulOdI%2#6JcqNxmJKz=fi)@5)4l4(Gk!H@%#%Vfv{k||)-3Jg&U<3P-O;C
zMIJ*ULlRI`B11Zmr!@JYsPNc;V!C;vCW*zz7Qh1~sY+zzzo4Ac!Hq
z*;3*#D<}nI5}N{?!6~2;E$$V7@tV(&3xtWlxJ?1dmH_!6(Hvl`7XafrA1G4NVn!JL;V{?~+9VYXc_Mhj0=~%}ni`wq_~qCqoAL8a){)+@nM)#wak7k5)aGkaYgob3T8c}!0hiei
A`Tzg`
diff --git a/Configurator/Configurator.vcxproj b/Configurator/Configurator.vcxproj
index 2752ad5..13f57a0 100644
--- a/Configurator/Configurator.vcxproj
+++ b/Configurator/Configurator.vcxproj
@@ -19,15 +19,17 @@
+
+
-
+
+
-
diff --git a/Configurator/resource.h b/Configurator/resource.h
index 187970e5279b8f775cfd5b11249dfa678af9951d..0a5b33c2f0c9d2e984979c0c2df293a695fe9578 100644
GIT binary patch
delta 122
zcmaDMI!}Cq8T;e|EG){-4E_uO43P}+3@!|=3}FnO49-A09!UB#_yVCLgWqIFR!K&S
m$rssWCtI<{5UE3aatfE!TS#2T~!
delta 28
kcmbOy{z7zv8T;f3> DeviceAPOInfo::loadAllInfos()
{
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);
+ DeviceAPOInfo info;
+ if(info.load(deviceGuidString))
+ result.push_back(info);
}
return result;
}
+bool DeviceAPOInfo::load(const wstring& deviceGuid)
+{
+ if(!RegistryHelper::keyExists(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties"))
+ return false;
+
+ this->deviceGuid = deviceGuid;
+ connectionName = RegistryHelper::readValue(renderKeyPath L"\\" + deviceGuid + L"\\Properties", connectionValueName);
+ deviceName = RegistryHelper::readValue(renderKeyPath L"\\" + deviceGuid + L"\\Properties", deviceValueName);
+ originalApoGuid = RegistryHelper::readValue(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties", apoGuidValueName);
+
+ GUID apoGuid;
+ if(!SUCCEEDED(CLSIDFromString(originalApoGuid.c_str(), &apoGuid)))
+ return false;
+
+ isInstalled = false;
+ if(apoGuid == __uuidof(EqualizerAPO))
+ isInstalled = true;
+
+ return true;
+}
+
void DeviceAPOInfo::install()
{
RegistryHelper::createKey(APP_REGPATH L"\\Child APOs");
@@ -69,7 +75,7 @@ void DeviceAPOInfo::install()
RegistryHelper::writeValue(APP_REGPATH L"\\Child APOs", deviceGuid, originalApoGuid);
RegistryHelper::saveToFile(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties", apoGuidValueName,
- L"backup_" + RegistryHelper::replaceIllegalCharacters(deviceName) + L"_" + RegistryHelper::replaceIllegalCharacters(connectionName) + L".reg");
+ L"backup_" + StringHelper::replaceIllegalCharacters(deviceName) + L"_" + StringHelper::replaceIllegalCharacters(connectionName) + L".reg");
RegistryHelper::writeValue(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties", apoGuidValueName, RegistryHelper::getGuidString(__uuidof(EqualizerAPO)));
}
diff --git a/Configurator/DeviceAPOInfo.h b/DeviceAPOInfo.h
similarity index 93%
rename from Configurator/DeviceAPOInfo.h
rename to DeviceAPOInfo.h
index aaf61bc..837748a 100644
--- a/Configurator/DeviceAPOInfo.h
+++ b/DeviceAPOInfo.h
@@ -26,6 +26,7 @@ class DeviceAPOInfo
{
public:
static std::vector loadAllInfos();
+ bool load(const std::wstring& deviceGuid);
void install();
void uninstall();
diff --git a/EqualizerAPO.cpp b/EqualizerAPO.cpp
index a48b751..f6d6f02 100644
--- a/EqualizerAPO.cpp
+++ b/EqualizerAPO.cpp
@@ -24,6 +24,7 @@
#include "LogHelper.h"
#include "RegistryHelper.h"
+#include "DeviceAPOInfo.h"
#include "EqualizerAPO.h"
using namespace std;
@@ -109,7 +110,12 @@ HRESULT EqualizerAPO::Initialize(UINT32 cbDataSize, BYTE* pbyData)
LogF(L"Can't read endpoint guid");
return hr;
}
- TraceF(L"Endpoint GUID: %s", var.pwszVal);
+ wstring deviceGuid = var.pwszVal;
+ TraceF(L"Endpoint GUID: %s", deviceGuid.c_str());
+
+ DeviceAPOInfo apoInfo;
+ if(apoInfo.load(deviceGuid))
+ peq.setDeviceInfo(apoInfo.deviceName, apoInfo.connectionName, apoInfo.deviceGuid);
wstring apoGuid;
try
diff --git a/EqualizerAPO.vcxproj b/EqualizerAPO.vcxproj
index e45cff2..e2b898a 100644
--- a/EqualizerAPO.vcxproj
+++ b/EqualizerAPO.vcxproj
@@ -158,20 +158,24 @@
+
+
+
+
diff --git a/ParametricEQ.cpp b/ParametricEQ.cpp
index 242ecf7..33098a6 100644
--- a/ParametricEQ.cpp
+++ b/ParametricEQ.cpp
@@ -22,10 +22,12 @@
#include
#include
#include
+#include
#define WIN32_LEAN_AND_MEAN
#include
#include
+#include "StringHelper.h"
#include "RegistryHelper.h"
#include "LogHelper.h"
#include "ParametricEQ.h"
@@ -77,6 +79,13 @@ ParametricEQ::~ParametricEQ()
}
}
+void ParametricEQ::setDeviceInfo(const wstring& deviceName, const wstring& connectionName, const wstring& deviceGuid)
+{
+ this->deviceName = deviceName;
+ this->connectionName = connectionName;
+ this->deviceGuid = deviceGuid;
+}
+
void ParametricEQ::initialize(float sampleRate, unsigned channelCount)
{
this->sampleRate = sampleRate;
@@ -135,32 +144,95 @@ void ParametricEQ::loadConfig(wstring path, unsigned& loadFilterCount, float& lo
return;
}
+ boolean deviceMatches = true;
+ wstring deviceString = StringHelper::toLowerCase(deviceName + L" " + connectionName + L" " + deviceGuid);
+
while(!inputStream.eof())
{
- string line;
- getline(inputStream, line);
+ string encodedLine;
+ getline(inputStream, encodedLine);
- size_t pos = line.find(':');
+ wstring line = StringHelper::toWString(encodedLine, CP_UTF8);
+ if(line.find(L'\uFFFD') != -1)
+ line = StringHelper::toWString(encodedLine, CP_ACP);
+
+ size_t pos = line.find(L':');
if(pos != -1)
{
- string key = line.substr(0, pos);
- string value = line.substr(pos + 1);
+ wstring key = line.substr(0, pos);
+ wstring value = line.substr(pos + 1);
- //Conversion to period as decimal mark, if needed
- for(unsigned i=0;i> fullList;
+ vector currentList;
+ wstring currentWord;
+
+ for(unsigned i=0; i 0)
+ {
+ currentList.push_back(currentWord);
+ currentWord.clear();
+ }
+ if(c == L';' && currentList.size() > 0)
+ {
+ fullList.push_back(currentList);
+ currentList.clear();
+ }
+ }
+ else
+ {
+ currentWord += value[i];
+ }
+ }
+
+ boolean matches = false;
+
+ 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()))
+ if(PathIsRelativeW(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';
+ filePath[path.size()] = L'\0';
else
- filePath[MAX_PATH - 1]=L'\0';
+ filePath[MAX_PATH - 1] = L'\0';
PathRemoveFileSpecW(filePath);
- PathAppendW(filePath, charBuf);
+ PathAppendW(filePath, value.c_str());
includePath = filePath;
}
else
- includePath = charBuf;
-
- delete charBuf;
+ includePath = value;
loadConfig(includePath, loadFilterCount, loadPreamp);
}
@@ -282,16 +351,15 @@ void ParametricEQ::process(float *output, float *input, unsigned frameCount)
}
}
-float ParametricEQ::getFreq(char* freqString)
+float ParametricEQ::getFreq(const wstring& freqString)
{
- size_t len = strlen(freqString);
float result;
- int matched = sscanf_s(freqString, "%f", &result);
+ int matched = swscanf_s(freqString.c_str(), L"%f", &result);
if(matched == 1)
{
- if(len >= 5)
+ if(freqString.length() >= 5)
{
- if(freqString[len - 4] == '.')
+ if(freqString[freqString.length() - 4] == L'.')
{
//Interpret as thousands separator because of Room EQ Wizard
result *= 1000.0f;
diff --git a/ParametricEQ.h b/ParametricEQ.h
index 800b4c5..dd34bd6 100644
--- a/ParametricEQ.h
+++ b/ParametricEQ.h
@@ -36,15 +36,19 @@ public:
ParametricEQ();
~ParametricEQ();
+ void setDeviceInfo(const std::wstring& deviceName, const std::wstring& connectionName, const std::wstring& deviceGuid);
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);
+ float getFreq(const std::wstring& freqString);
static unsigned long __stdcall notificationThread(void* parameter);
+ std::wstring deviceName;
+ std::wstring connectionName;
+ std::wstring deviceGuid;
std::wstring configPath;
float sampleRate;
unsigned channelCount;
diff --git a/RegistryHelper.cpp b/RegistryHelper.cpp
index eebe9cf..4f0593b 100644
--- a/RegistryHelper.cpp
+++ b/RegistryHelper.cpp
@@ -212,34 +212,6 @@ wstring RegistryHelper::getGuidString(GUID guid)
return result;
}
-wstring RegistryHelper::replaceIllegalCharacters(wstring filename)
-{
- wstringstream stream;
-
- for(unsigned i=0; i':
- case L':':
- case L'"':
- case L'/':
- case L'\\':
- case L'|':
- case L'?':
- case L'*':
- stream.put(L'_');
- break;
- default:
- stream.put(c);
- }
- }
-
- return stream.str();
-}
-
wstring RegistryHelper::getSystemErrorString(long status)
{
wchar_t* buf;
diff --git a/RegistryHelper.h b/RegistryHelper.h
index ca7ae57..64f2094 100644
--- a/RegistryHelper.h
+++ b/RegistryHelper.h
@@ -38,7 +38,6 @@ public:
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);
- static std::wstring replaceIllegalCharacters(std::wstring filename);
private:
static std::wstring getSystemErrorString(long status);
diff --git a/StringHelper.cpp b/StringHelper.cpp
new file mode 100644
index 0000000..b0d9ade
--- /dev/null
+++ b/StringHelper.cpp
@@ -0,0 +1,56 @@
+
+#include
+#include
+#define WIN32_LEAN_AND_MEAN
+#include
+#include "StringHelper.h"
+
+using namespace std;
+
+wstring StringHelper::replaceCharacters(std::wstring s, std::wstring chars, wchar_t replacement)
+{
+ wstring result;
+ result.reserve(s.length());
+
+ for(unsigned i=0; i:\"/\\|?*", '_');
+}
+
+wstring StringHelper::toWString(string s, unsigned codepage)
+{
+ int length = MultiByteToWideChar(codepage, 0, s.c_str(), -1, NULL, 0);
+ wchar_t* charBuf = new wchar_t[length];
+ MultiByteToWideChar(codepage, 0, s.c_str(), -1, charBuf, length);
+ wstring result = charBuf;
+ delete charBuf;
+
+ return result;
+}
+
+wstring StringHelper::toLowerCase(wstring s)
+{
+ wchar_t* charBuf = new wchar_t[s.length() + 1];
+ memcpy(charBuf, s.c_str(), (s.length() + 1) * sizeof(wchar_t));
+ errno_t err = _wcslwr_s(charBuf, s.length() + 1);
+
+ wstring result = charBuf;
+ delete charBuf;
+
+ if(err == 0)
+ return result;
+ else
+ return s;
+}
diff --git a/StringHelper.h b/StringHelper.h
new file mode 100644
index 0000000..f7ecc0f
--- /dev/null
+++ b/StringHelper.h
@@ -0,0 +1,32 @@
+/*
+ This file is part of EqualizerAPO, a system-wide equalizer.
+ Copyright (C) 2013 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 StringHelper
+{
+public:
+ static std::wstring replaceCharacters(std::wstring s, std::wstring chars, wchar_t replacement);
+ static std::wstring replaceIllegalCharacters(std::wstring filename);
+ static std::wstring toWString(std::string s, unsigned codepage);
+ static std::wstring toLowerCase(std::wstring s);
+};