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 b848a81..70a8074 100644
Binary files a/Configurator/Configurator.rc and b/Configurator/Configurator.rc differ
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 187970e..0a5b33c 100644
Binary files a/Configurator/resource.h and b/Configurator/resource.h differ
diff --git a/Configurator/DeviceAPOInfo.cpp b/DeviceAPOInfo.cpp
similarity index 67%
rename from Configurator/DeviceAPOInfo.cpp
rename to DeviceAPOInfo.cpp
index 97588a8..8e7543c 100644
--- a/Configurator/DeviceAPOInfo.cpp
+++ b/DeviceAPOInfo.cpp
@@ -19,9 +19,10 @@
#include "DeviceAPOInfo.h"
-#include "../EqualizerAPO.h"
-#include "../ParametricEQ.h"
-#include "../RegistryHelper.h"
+#include "EqualizerAPO.h"
+#include "ParametricEQ.h"
+#include "StringHelper.h"
+#include "RegistryHelper.h"
using namespace std;
@@ -38,30 +39,35 @@ vector 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);
+};