Added: Voicemeeter audio processing support. When Voicemeeter is installed, it can be selected in the Configurator.
This commit is contained in:
1 parent
46d921945f
commit
989812ba36
55 files changed
+3044
-278
No files matched your search
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
This file is part of EqualizerAPO, a system-wide equalizer.
|
||||
Copyright (C) 2017 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 "stdafx.h"
|
||||
#include "AbstractAPOInfo.h"
|
||||
|
||||
AbstractAPOInfo::~AbstractAPOInfo()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
This file is part of EqualizerAPO, a system-wide equalizer.
|
||||
Copyright (C) 2017 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 <string>
|
||||
|
||||
class AbstractAPOInfo
|
||||
{
|
||||
public:
|
||||
virtual ~AbstractAPOInfo();
|
||||
virtual std::wstring getConnectionName() const = 0;
|
||||
virtual std::wstring getDeviceName() const = 0;
|
||||
virtual std::wstring getDeviceGuid() const = 0;
|
||||
virtual std::wstring getDeviceString() const = 0;
|
||||
virtual unsigned getChannelCount() const = 0;
|
||||
virtual unsigned getSampleRate() const = 0;
|
||||
virtual unsigned long getChannelMask() const = 0;
|
||||
virtual bool isInput() const = 0;
|
||||
virtual bool isInstalled() const = 0;
|
||||
virtual bool canBeUpgraded() const = 0;
|
||||
virtual bool hasChanges() const = 0;
|
||||
virtual bool isExperimental() const = 0;
|
||||
virtual bool isEnhancementsDisabled() const = 0;
|
||||
virtual bool isDefaultDevice() const = 0;
|
||||
virtual void install() = 0;
|
||||
virtual void uninstall() = 0;
|
||||
virtual void reinstall() = 0;
|
||||
};
|
||||
@@ -164,9 +164,10 @@ int main(int argc, char** argv)
|
||||
timer.start();
|
||||
|
||||
FilterEngine engine;
|
||||
engine.setDeviceInfo(false, true, StringHelper::toWString(devicenameArg.getValue(), CP_ACP),
|
||||
StringHelper::toWString(connectionnameArg.getValue(), CP_ACP),
|
||||
StringHelper::toWString(guidArg.getValue(), CP_ACP));
|
||||
wstring deviceName = StringHelper::toWString(devicenameArg.getValue(), CP_ACP);
|
||||
wstring connectionName = StringHelper::toWString(connectionnameArg.getValue(), CP_ACP);
|
||||
wstring deviceGuid = StringHelper::toWString(guidArg.getValue(), CP_ACP);
|
||||
engine.setDeviceInfo(false, true, deviceName, connectionName, deviceGuid, deviceName + L" " + connectionName + L" " + deviceGuid);
|
||||
engine.initialize((float)sampleRate, channelCount, channelCount, channelCount, channelMask, batchsize);
|
||||
|
||||
double initTime = timer.stop();
|
||||
|
||||
@@ -224,7 +224,9 @@
|
||||
<ClInclude Include="..\helpers\MemoryHelper.h" />
|
||||
<ClInclude Include="..\helpers\PrecisionTimer.h" />
|
||||
<ClInclude Include="..\helpers\RegistryHelper.h" />
|
||||
<ClInclude Include="..\helpers\ScopeGuard.h" />
|
||||
<ClInclude Include="..\helpers\StringHelper.h" />
|
||||
<ClInclude Include="..\helpers\UncaughtExceptions.h" />
|
||||
<ClInclude Include="..\IFilter.h" />
|
||||
<ClInclude Include="..\IFilterFactory.h" />
|
||||
<ClInclude Include="..\libHybridConv-0.1.1\libHybridConv_eapo.h" />
|
||||
|
||||
@@ -208,6 +208,12 @@
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\stdafx.h" />
|
||||
<ClInclude Include="..\helpers\ScopeGuard.h">
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\helpers\UncaughtExceptions.h">
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="parser">
|
||||
|
||||
+121
-71
@@ -25,6 +25,7 @@
|
||||
#include <ObjBase.h>
|
||||
#include "helpers/StringHelper.h"
|
||||
#include "helpers/RegistryHelper.h"
|
||||
#include "VoicemeeterAPOInfo.h"
|
||||
#include "Configurator.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -176,26 +177,37 @@ void Configurator::onInitDialog(HWND hDlg)
|
||||
wstring defaultDevice = StringHelper::toLowerCase(DeviceAPOInfo::getDefaultDevice(i == 1));
|
||||
|
||||
int itemCount = 0;
|
||||
for (vector<DeviceAPOInfo>::iterator it = apoInfos[i].begin(); it != apoInfos[i].end(); it++)
|
||||
for (shared_ptr<AbstractAPOInfo>& apoInfo : apoInfos[i])
|
||||
{
|
||||
wcsncpy_s(stringBuf, sizeof(stringBuf) / sizeof(wchar_t), it->connectionName.c_str(), _TRUNCATE);
|
||||
wcsncpy_s(stringBuf, sizeof(stringBuf) / sizeof(wchar_t), apoInfo->getConnectionName().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);
|
||||
wcsncpy_s(stringBuf, sizeof(stringBuf) / sizeof(wchar_t), apoInfo->getDeviceName().c_str(), _TRUNCATE);
|
||||
ListView_SetItemText(deviceList, itemCount, 1, stringBuf);
|
||||
|
||||
if (it->isInstalled)
|
||||
VoicemeeterAPOInfo* voicemeeterInfo = dynamic_cast<VoicemeeterAPOInfo*>(apoInfo.get());
|
||||
if (apoInfo->isInstalled())
|
||||
{
|
||||
ListView_SetCheckState(deviceList, itemCount, TRUE);
|
||||
if (it->canBeUpgraded())
|
||||
LoadStringW(hInstance, IDS_WILL_BE_UPGRADED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
else if (it->isEnhancementsDisabled)
|
||||
LoadStringW(hInstance, IDS_ENHANCEMENTS_WILL_BE_ENABLED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
if (voicemeeterInfo != NULL && !voicemeeterInfo->isVoicemeeterInstalled())
|
||||
{
|
||||
ListView_SetCheckState(deviceList, itemCount, FALSE);
|
||||
LoadStringW(hInstance, IDS_WILL_BE_UNINSTALLED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
}
|
||||
else
|
||||
LoadStringW(hInstance, IDS_ALREADY_INSTALLED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
{
|
||||
ListView_SetCheckState(deviceList, itemCount, TRUE);
|
||||
if (apoInfo->canBeUpgraded())
|
||||
LoadStringW(hInstance, IDS_WILL_BE_UPGRADED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
else if (apoInfo->hasChanges())
|
||||
LoadStringW(hInstance, IDS_WILL_BE_CHANGED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
else if (apoInfo->isEnhancementsDisabled())
|
||||
LoadStringW(hInstance, IDS_ENHANCEMENTS_WILL_BE_ENABLED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
else
|
||||
LoadStringW(hInstance, IDS_ALREADY_INSTALLED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
}
|
||||
}
|
||||
else if (it->isExperimental())
|
||||
else if (apoInfo->isExperimental())
|
||||
{
|
||||
LoadStringW(hInstance, IDS_CAN_BE_INSTALLED_EXPERIMENTAL, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
}
|
||||
@@ -204,7 +216,15 @@ void Configurator::onInitDialog(HWND hDlg)
|
||||
LoadStringW(hInstance, IDS_CAN_BE_INSTALLED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
}
|
||||
|
||||
if (it->isDefaultDevice)
|
||||
if (voicemeeterInfo != NULL && !voicemeeterInfo->isVoicemeeterInstalled())
|
||||
{
|
||||
wstring statusText = stringBuf;
|
||||
LoadStringW(hInstance, IDS_VOICEMEETER_WAS_UNINSTALLED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
statusText = wstring(stringBuf) + L", " + statusText;
|
||||
|
||||
ListView_SetItemText(deviceList, itemCount, 2, const_cast<wchar_t*>(statusText.c_str()));
|
||||
}
|
||||
else if (apoInfo->isDefaultDevice())
|
||||
{
|
||||
wstring statusText = stringBuf;
|
||||
LoadStringW(hInstance, IDS_DEFAULT_DEVICE, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
@@ -250,6 +270,8 @@ void Configurator::onLvnItemChanged(unsigned sourceId, LPNMLISTVIEW info)
|
||||
|
||||
bool Configurator::onButtonClicked(unsigned sourceId)
|
||||
{
|
||||
bool deviceUpdated = false;
|
||||
|
||||
switch (sourceId)
|
||||
{
|
||||
case IDOK:
|
||||
@@ -268,16 +290,25 @@ bool Configurator::onButtonClicked(unsigned sourceId)
|
||||
|
||||
try
|
||||
{
|
||||
DeviceAPOInfo info = apoInfos[index][item.lParam];
|
||||
if (ListView_GetCheckState(deviceList, i) && !info.isInstalled)
|
||||
info.install();
|
||||
else if (!ListView_GetCheckState(deviceList, i) && info.isInstalled)
|
||||
info.uninstall();
|
||||
else if (ListView_GetCheckState(deviceList, i) && (info.canBeUpgraded() || info.hasChanges() || info.isEnhancementsDisabled))
|
||||
shared_ptr<AbstractAPOInfo>& info = apoInfos[index][item.lParam];
|
||||
DeviceAPOInfo* deviceInfo = dynamic_cast<DeviceAPOInfo*>(info.get());
|
||||
if (ListView_GetCheckState(deviceList, i) && !info->isInstalled())
|
||||
{
|
||||
info.uninstall();
|
||||
info.load(info.deviceGuid);
|
||||
info.install();
|
||||
info->install();
|
||||
if (deviceInfo != NULL)
|
||||
deviceUpdated = true;
|
||||
}
|
||||
else if (!ListView_GetCheckState(deviceList, i) && info->isInstalled())
|
||||
{
|
||||
info->uninstall();
|
||||
if (deviceInfo != NULL)
|
||||
deviceUpdated = true;
|
||||
}
|
||||
else if (ListView_GetCheckState(deviceList, i) && (info->canBeUpgraded() || info->hasChanges() || info->isEnhancementsDisabled()))
|
||||
{
|
||||
info->reinstall();
|
||||
if (deviceInfo != NULL)
|
||||
deviceUpdated = true;
|
||||
}
|
||||
}
|
||||
catch (RegistryException e)
|
||||
@@ -286,6 +317,8 @@ bool Configurator::onButtonClicked(unsigned sourceId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VoicemeeterAPOInfo::ensureVoicemeeterClientRunning();
|
||||
}
|
||||
break;
|
||||
case IDC_COPY_DEVICE_COMMAND:
|
||||
@@ -312,8 +345,8 @@ bool Configurator::onButtonClicked(unsigned sourceId)
|
||||
else
|
||||
command += L"; ";
|
||||
|
||||
DeviceAPOInfo info = apoInfos[index][item.lParam];
|
||||
command += StringHelper::replaceCharacters(info.deviceName + L" " + info.connectionName + L" " + info.deviceGuid, L";", L" ");
|
||||
shared_ptr<AbstractAPOInfo>& info = apoInfos[index][item.lParam];
|
||||
command += StringHelper::replaceCharacters(info->getDeviceString(), L";", L" ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,31 +390,34 @@ bool Configurator::onButtonClicked(unsigned sourceId)
|
||||
|
||||
if (item.state & LVIS_SELECTED)
|
||||
{
|
||||
DeviceAPOInfo& info = apoInfos[index][item.lParam];
|
||||
|
||||
switch (sourceId)
|
||||
shared_ptr<AbstractAPOInfo>& info = apoInfos[index][item.lParam];
|
||||
DeviceAPOInfo* deviceInfo = dynamic_cast<DeviceAPOInfo*>(info.get());
|
||||
if (deviceInfo != NULL)
|
||||
{
|
||||
case IDC_INSTALL_PRE_MIX:
|
||||
info.selectedInstallState.installPreMix = Button_GetCheck(installPreMix) == BST_CHECKED;
|
||||
break;
|
||||
case IDC_INSTALL_POST_MIX:
|
||||
info.selectedInstallState.installPostMix = Button_GetCheck(installPostMix) == BST_CHECKED;
|
||||
break;
|
||||
case IDC_USE_ORIGINAL_APO_PRE_MIX:
|
||||
info.selectedInstallState.useOriginalAPOPreMix = Button_GetCheck(useOriginalAPOPreMix) == BST_CHECKED;
|
||||
break;
|
||||
case IDC_USE_ORIGINAL_APO_POST_MIX:
|
||||
info.selectedInstallState.useOriginalAPOPostMix = Button_GetCheck(useOriginalAPOPostMix) == BST_CHECKED;
|
||||
break;
|
||||
case IDC_INSTALL_MODE_COMBOBOX:
|
||||
info.selectedInstallState.installMode = (DeviceAPOInfo::InstallMode)ComboBox_GetCurSel(installModeComboBox);
|
||||
break;
|
||||
case IDC_ALLOW_SILENT_BUFFER:
|
||||
info.selectedInstallState.allowSilentBufferModification = Button_GetCheck(allowSilentBuffer) == BST_CHECKED;
|
||||
break;
|
||||
}
|
||||
switch (sourceId)
|
||||
{
|
||||
case IDC_INSTALL_PRE_MIX:
|
||||
deviceInfo->getSelectedInstallState().installPreMix = Button_GetCheck(installPreMix) == BST_CHECKED;
|
||||
break;
|
||||
case IDC_INSTALL_POST_MIX:
|
||||
deviceInfo->getSelectedInstallState().installPostMix = Button_GetCheck(installPostMix) == BST_CHECKED;
|
||||
break;
|
||||
case IDC_USE_ORIGINAL_APO_PRE_MIX:
|
||||
deviceInfo->getSelectedInstallState().useOriginalAPOPreMix = Button_GetCheck(useOriginalAPOPreMix) == BST_CHECKED;
|
||||
break;
|
||||
case IDC_USE_ORIGINAL_APO_POST_MIX:
|
||||
deviceInfo->getSelectedInstallState().useOriginalAPOPostMix = Button_GetCheck(useOriginalAPOPostMix) == BST_CHECKED;
|
||||
break;
|
||||
case IDC_INSTALL_MODE_COMBOBOX:
|
||||
deviceInfo->getSelectedInstallState().installMode = (DeviceAPOInfo::InstallMode)ComboBox_GetCurSel(installModeComboBox);
|
||||
break;
|
||||
case IDC_ALLOW_SILENT_BUFFER:
|
||||
deviceInfo->getSelectedInstallState().allowSilentBufferModification = Button_GetCheck(allowSilentBuffer) == BST_CHECKED;
|
||||
break;
|
||||
}
|
||||
|
||||
updateList(index, i);
|
||||
updateList(index, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,7 +444,7 @@ bool Configurator::onButtonClicked(unsigned sourceId)
|
||||
LoadStringW(hInstance, IDS_AFTERINSTALL, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
MessageBoxW(hDlg, stringBuf, L"Info", MB_ICONINFORMATION | MB_OK);
|
||||
}
|
||||
else if (sourceId == IDOK && RegistryHelper::isWindowsVersionAtLeast(6, 3) // Windows 8.1
|
||||
else if (sourceId == IDOK && deviceUpdated && RegistryHelper::isWindowsVersionAtLeast(6, 3) // Windows 8.1
|
||||
|| askForReboot)
|
||||
{
|
||||
wchar_t captionBuf[255];
|
||||
@@ -470,7 +506,6 @@ bool Configurator::isAnySelected()
|
||||
item.iSubItem = 0;
|
||||
item.mask = LVIF_PARAM;
|
||||
ListView_GetItem(deviceList, &item);
|
||||
DeviceAPOInfo apoInfo = apoInfos[index][item.lParam];
|
||||
if (ListView_GetCheckState(deviceList, i) != 0)
|
||||
{
|
||||
anySelected = true;
|
||||
@@ -497,9 +532,9 @@ bool Configurator::isChanged()
|
||||
item.iSubItem = 0;
|
||||
item.mask = LVIF_PARAM;
|
||||
ListView_GetItem(deviceList, &item);
|
||||
DeviceAPOInfo apoInfo = apoInfos[index][item.lParam];
|
||||
if ((ListView_GetCheckState(deviceList, i) != 0) != apoInfo.isInstalled
|
||||
|| ListView_GetCheckState(deviceList, i) && apoInfo.isInstalled && (apoInfo.canBeUpgraded() || apoInfo.hasChanges() || apoInfo.isEnhancementsDisabled))
|
||||
shared_ptr<AbstractAPOInfo>& apoInfo = apoInfos[index][item.lParam];
|
||||
if ((ListView_GetCheckState(deviceList, i) != 0) != apoInfo->isInstalled()
|
||||
|| ListView_GetCheckState(deviceList, i) && apoInfo->isInstalled() && (apoInfo->canBeUpgraded() || apoInfo->hasChanges() || apoInfo->isEnhancementsDisabled()))
|
||||
{
|
||||
changed = true;
|
||||
break;
|
||||
@@ -525,8 +560,8 @@ bool Configurator::hasUpgrades()
|
||||
item.iSubItem = 0;
|
||||
item.mask = LVIF_PARAM;
|
||||
ListView_GetItem(deviceList, &item);
|
||||
DeviceAPOInfo apoInfo = apoInfos[index][item.lParam];
|
||||
if (ListView_GetCheckState(deviceList, i) && apoInfo.isInstalled && (apoInfo.canBeUpgraded() || apoInfo.isEnhancementsDisabled))
|
||||
shared_ptr<AbstractAPOInfo>& apoInfo = apoInfos[index][item.lParam];
|
||||
if (ListView_GetCheckState(deviceList, i) && apoInfo->isInstalled() && (apoInfo->canBeUpgraded() || apoInfo->isEnhancementsDisabled()))
|
||||
{
|
||||
hasUpgrades = true;
|
||||
break;
|
||||
@@ -586,27 +621,36 @@ void Configurator::updateList(int listIndex, int itemIndex)
|
||||
|
||||
if (apoInfos[listIndex].size() == itemCount)
|
||||
{
|
||||
DeviceAPOInfo apoInfo = apoInfos[listIndex][itemIndex];
|
||||
shared_ptr<AbstractAPOInfo>& apoInfo = apoInfos[listIndex][itemIndex];
|
||||
bool checked = ListView_GetCheckState(deviceList, itemIndex) != 0;
|
||||
wchar_t stringBuf[255];
|
||||
if (checked && !apoInfo.isInstalled)
|
||||
if (checked && !apoInfo->isInstalled())
|
||||
LoadStringW(hInstance, IDS_WILL_BE_INSTALLED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
else if (!checked && apoInfo.isInstalled)
|
||||
else if (!checked && apoInfo->isInstalled())
|
||||
LoadStringW(hInstance, IDS_WILL_BE_UNINSTALLED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
else if (apoInfo.isInstalled && apoInfo.canBeUpgraded())
|
||||
else if (apoInfo->isInstalled() && apoInfo->canBeUpgraded())
|
||||
LoadStringW(hInstance, IDS_WILL_BE_UPGRADED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
else if (apoInfo.isInstalled && apoInfo.hasChanges())
|
||||
else if (apoInfo->isInstalled() && apoInfo->hasChanges())
|
||||
LoadStringW(hInstance, IDS_WILL_BE_CHANGED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
else if (apoInfo.isInstalled && apoInfo.isEnhancementsDisabled)
|
||||
else if (apoInfo->isInstalled() && apoInfo->isEnhancementsDisabled())
|
||||
LoadStringW(hInstance, IDS_ENHANCEMENTS_WILL_BE_ENABLED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
else if (apoInfo.isInstalled)
|
||||
else if (apoInfo->isInstalled())
|
||||
LoadStringW(hInstance, IDS_ALREADY_INSTALLED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
else if (apoInfo.isExperimental())
|
||||
else if (apoInfo->isExperimental())
|
||||
LoadStringW(hInstance, IDS_CAN_BE_INSTALLED_EXPERIMENTAL, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
else
|
||||
LoadStringW(hInstance, IDS_CAN_BE_INSTALLED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
|
||||
if (apoInfo.isDefaultDevice)
|
||||
VoicemeeterAPOInfo* voicemeeterInfo = dynamic_cast<VoicemeeterAPOInfo*>(apoInfo.get());
|
||||
if (voicemeeterInfo != NULL && !voicemeeterInfo->isVoicemeeterInstalled())
|
||||
{
|
||||
wstring statusText = stringBuf;
|
||||
LoadStringW(hInstance, IDS_VOICEMEETER_WAS_UNINSTALLED, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
statusText = wstring(stringBuf) + L", " + statusText;
|
||||
|
||||
ListView_SetItemText(deviceList, itemCount, 2, const_cast<wchar_t*>(statusText.c_str()));
|
||||
}
|
||||
else if (apoInfo->isDefaultDevice())
|
||||
{
|
||||
wstring statusText = stringBuf;
|
||||
LoadStringW(hInstance, IDS_DEFAULT_DEVICE, stringBuf, sizeof(stringBuf) / sizeof(wchar_t));
|
||||
@@ -658,11 +702,15 @@ void Configurator::updateButtons(int listIndex)
|
||||
{
|
||||
enable = ListView_GetCheckState(deviceList, selectedIndex) != 0;
|
||||
|
||||
DeviceAPOInfo apoInfo = apoInfos[listIndex][selectedIndex];
|
||||
isInput = apoInfo.isInput;
|
||||
hasOriginalAPOPreMix = apoInfo.getOriginalAPOPreMix() != L"";
|
||||
hasOriginalAPOPostMix = apoInfo.getOriginalAPOPostMix() != L"";
|
||||
installState = apoInfo.selectedInstallState;
|
||||
shared_ptr<AbstractAPOInfo>& apoInfo = apoInfos[listIndex][selectedIndex];
|
||||
DeviceAPOInfo* deviceApoInfo = dynamic_cast<DeviceAPOInfo*>(apoInfo.get());
|
||||
if (deviceApoInfo != NULL)
|
||||
{
|
||||
isInput = deviceApoInfo->isInput();
|
||||
hasOriginalAPOPreMix = deviceApoInfo->getOriginalAPOPreMix() != L"";
|
||||
hasOriginalAPOPostMix = deviceApoInfo->getOriginalAPOPostMix() != L"";
|
||||
installState = deviceApoInfo->getSelectedInstallState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -709,14 +757,14 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
|
||||
{
|
||||
for (int index = 0; index <= 1; index++)
|
||||
{
|
||||
vector<DeviceAPOInfo> apoInfos = DeviceAPOInfo::loadAllInfos(index == 1);
|
||||
vector<shared_ptr<AbstractAPOInfo> > apoInfos = DeviceAPOInfo::loadAllInfos(index == 1);
|
||||
|
||||
for (vector<DeviceAPOInfo>::iterator it = apoInfos.begin(); it != apoInfos.end(); it++)
|
||||
for (shared_ptr<AbstractAPOInfo>& apoInfo : apoInfos)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (it->isInstalled)
|
||||
it->uninstall();
|
||||
if (apoInfo->isInstalled())
|
||||
apoInfo->uninstall();
|
||||
}
|
||||
catch (RegistryException e)
|
||||
{
|
||||
@@ -725,6 +773,8 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VoicemeeterAPOInfo::ensureVoicemeeterClientRunning();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "resource.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "DeviceAPOInfo.h"
|
||||
|
||||
class Configurator
|
||||
@@ -63,6 +64,6 @@ private:
|
||||
void updateList(int listIndex, int itemIndex);
|
||||
void updateButtons(int listIndex);
|
||||
|
||||
std::vector<DeviceAPOInfo> apoInfos[2];
|
||||
std::vector<std::shared_ptr<AbstractAPOInfo> > apoInfos[2];
|
||||
bool askForReboot = false;
|
||||
};
|
||||
Binary file not shown.
@@ -19,17 +19,22 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\AbstractAPOInfo.h" />
|
||||
<ClInclude Include="..\DeviceAPOInfo.h" />
|
||||
<ClInclude Include="..\helpers\LogHelper.h" />
|
||||
<ClInclude Include="..\helpers\MemoryHelper.h" />
|
||||
<ClInclude Include="..\helpers\PrecisionTimer.h" />
|
||||
<ClInclude Include="..\helpers\RegistryHelper.h" />
|
||||
<ClInclude Include="..\helpers\ScopeGuard.h" />
|
||||
<ClInclude Include="..\helpers\StringHelper.h" />
|
||||
<ClInclude Include="..\helpers\UncaughtExceptions.h" />
|
||||
<ClInclude Include="..\stdafx.h" />
|
||||
<ClInclude Include="..\VoicemeeterAPOInfo.h" />
|
||||
<ClInclude Include="Configurator.h" />
|
||||
<ClInclude Include="Resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\AbstractAPOInfo.cpp" />
|
||||
<ClCompile Include="..\DeviceAPOInfo.cpp" />
|
||||
<ClCompile Include="..\helpers\LogHelper.cpp" />
|
||||
<ClCompile Include="..\helpers\MemoryHelper.cpp" />
|
||||
@@ -41,6 +46,7 @@
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\VoicemeeterAPOInfo.cpp" />
|
||||
<ClCompile Include="Configurator.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -12,10 +12,12 @@
|
||||
<ClCompile Include="..\helpers\RegistryHelper.cpp">
|
||||
<Filter>helpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\stdafx.cpp" />
|
||||
<ClCompile Include="..\helpers\StringHelper.cpp">
|
||||
<Filter>helpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\stdafx.cpp" />
|
||||
<ClCompile Include="..\AbstractAPOInfo.cpp" />
|
||||
<ClCompile Include="..\VoicemeeterAPOInfo.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\DeviceAPOInfo.h" />
|
||||
@@ -33,10 +35,18 @@
|
||||
<ClInclude Include="..\helpers\RegistryHelper.h">
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\stdafx.h" />
|
||||
<ClInclude Include="..\helpers\StringHelper.h">
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\stdafx.h" />
|
||||
<ClInclude Include="..\AbstractAPOInfo.h" />
|
||||
<ClInclude Include="..\VoicemeeterAPOInfo.h" />
|
||||
<ClInclude Include="..\helpers\ScopeGuard.h">
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\helpers\UncaughtExceptions.h">
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Configurator.rc" />
|
||||
|
||||
Binary file not shown.
+115
-28
@@ -23,6 +23,7 @@
|
||||
#include <shellapi.h>
|
||||
|
||||
#include "DeviceAPOInfo.h"
|
||||
#include "VoicemeeterAPOInfo.h"
|
||||
|
||||
#include "helpers/StringHelper.h"
|
||||
#include "helpers/RegistryHelper.h"
|
||||
@@ -69,23 +70,27 @@ static const wchar_t* disableEnhancementsValueName = L"{1da5d803-d492-4edd-8c23-
|
||||
static const wchar_t* installVersion = L"2";
|
||||
static PROPERTYKEY guidPropertyKey = {{0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e}, 4};
|
||||
|
||||
vector<DeviceAPOInfo> DeviceAPOInfo::loadAllInfos(bool input)
|
||||
vector<shared_ptr<AbstractAPOInfo> > DeviceAPOInfo::loadAllInfos(bool input)
|
||||
{
|
||||
vector<DeviceAPOInfo> result;
|
||||
vector<shared_ptr<AbstractAPOInfo> > result;
|
||||
|
||||
vector<wstring> deviceGuidStrings = RegistryHelper::enumSubKeys(input ? captureKeyPath : renderKeyPath);
|
||||
wstring defaultDeviceGuid = getDefaultDevice(input);
|
||||
for (vector<wstring>::iterator it = deviceGuidStrings.begin(); it != deviceGuidStrings.end(); it++)
|
||||
{
|
||||
wstring deviceGuidString = *it;
|
||||
|
||||
DeviceAPOInfo info;
|
||||
if (info.load(deviceGuidString, defaultDeviceGuid))
|
||||
shared_ptr<DeviceAPOInfo> info = make_shared<DeviceAPOInfo>();
|
||||
if (info->load(deviceGuidString, defaultDeviceGuid))
|
||||
{
|
||||
info.selectedInstallState = info.currentInstallState;
|
||||
result.push_back(info);
|
||||
info->selectedInstallState = info->currentInstallState;
|
||||
result.push_back(move(info));
|
||||
}
|
||||
}
|
||||
|
||||
if (!input)
|
||||
VoicemeeterAPOInfo::prependInfos(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -170,12 +175,12 @@ bool DeviceAPOInfo::load(const wstring& deviceGuid, wstring defaultDeviceGuid)
|
||||
if (RegistryHelper::keyExists(renderKeyPath L"\\" + deviceGuid))
|
||||
{
|
||||
keyPath = renderKeyPath L"\\" + deviceGuid;
|
||||
isInput = false;
|
||||
input = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
keyPath = captureKeyPath L"\\" + deviceGuid;
|
||||
isInput = true;
|
||||
input = true;
|
||||
}
|
||||
|
||||
unsigned long deviceState = RegistryHelper::readDWORDValue(keyPath, L"DeviceState");
|
||||
@@ -209,27 +214,27 @@ bool DeviceAPOInfo::load(const wstring& deviceGuid, wstring defaultDeviceGuid)
|
||||
channelMask = RegistryHelper::readDWORDValue(keyPath + L"\\Properties", channelMaskValueName);
|
||||
|
||||
if (defaultDeviceGuid == L"")
|
||||
defaultDeviceGuid = getDefaultDevice(isInput);
|
||||
defaultDeviceGuid = getDefaultDevice(input);
|
||||
|
||||
GUID guid1, guid2;
|
||||
if (SUCCEEDED(CLSIDFromString(deviceGuid.c_str(), &guid1)) && SUCCEEDED(CLSIDFromString(defaultDeviceGuid.c_str(), &guid2)))
|
||||
isDefaultDevice = (guid1 == guid2) != 0;
|
||||
defaultDevice = (guid1 == guid2) != 0;
|
||||
else
|
||||
isDefaultDevice = false;
|
||||
defaultDevice = false;
|
||||
|
||||
isEnhancementsDisabled = false;
|
||||
enhancementsDisabled = false;
|
||||
if (RegistryHelper::keyExists(keyPath + L"\\FxProperties") && RegistryHelper::valueExists(keyPath + L"\\FxProperties", disableEnhancementsValueName))
|
||||
isEnhancementsDisabled = RegistryHelper::readDWORDValue(keyPath + L"\\FxProperties", disableEnhancementsValueName) != 0;
|
||||
enhancementsDisabled = RegistryHelper::readDWORDValue(keyPath + L"\\FxProperties", disableEnhancementsValueName) != 0;
|
||||
|
||||
isInstalled = false;
|
||||
installed = false;
|
||||
currentInstallState.installMode = INSTALL_LFX_GFX;
|
||||
version = L"0";
|
||||
preMixChildGuid = L"";
|
||||
postMixChildGuid = L"";
|
||||
currentInstallState.installPreMix = true;
|
||||
currentInstallState.installPostMix = !isInput;
|
||||
currentInstallState.installPostMix = !input;
|
||||
currentInstallState.useOriginalAPOPreMix = true;
|
||||
currentInstallState.useOriginalAPOPostMix = !isInput;
|
||||
currentInstallState.useOriginalAPOPostMix = !input;
|
||||
currentInstallState.allowSilentBufferModification = false;
|
||||
|
||||
if (!RegistryHelper::keyExists(keyPath + L"\\FxProperties"))
|
||||
@@ -271,7 +276,7 @@ bool DeviceAPOInfo::load(const wstring& deviceGuid, wstring defaultDeviceGuid)
|
||||
|
||||
if (found)
|
||||
{
|
||||
isInstalled = true;
|
||||
installed = true;
|
||||
|
||||
if (RegistryHelper::keyExists(childApoPath L"\\" + deviceGuid))
|
||||
{
|
||||
@@ -352,19 +357,19 @@ bool DeviceAPOInfo::load(const wstring& deviceGuid, wstring defaultDeviceGuid)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceAPOInfo::canBeUpgraded()
|
||||
bool DeviceAPOInfo::canBeUpgraded() const
|
||||
{
|
||||
return isInstalled && version != installVersion;
|
||||
return installed && version != installVersion;
|
||||
}
|
||||
|
||||
bool DeviceAPOInfo::hasChanges()
|
||||
bool DeviceAPOInfo::hasChanges() const
|
||||
{
|
||||
return isInstalled && selectedInstallState != currentInstallState;
|
||||
return installed && selectedInstallState != currentInstallState;
|
||||
}
|
||||
|
||||
bool DeviceAPOInfo::isExperimental()
|
||||
bool DeviceAPOInfo::isExperimental() const
|
||||
{
|
||||
return !isInstalled && originalApoGuids[0] == APOGUID_NOKEY;
|
||||
return !installed && originalApoGuids[0] == APOGUID_NOKEY;
|
||||
}
|
||||
|
||||
wstring DeviceAPOInfo::getOriginalAPOPreMix()
|
||||
@@ -438,7 +443,7 @@ void DeviceAPOInfo::install()
|
||||
RegistryHelper::createKey(childApoPath L"\\" + deviceGuid);
|
||||
|
||||
wstring keyPath;
|
||||
if (!isInput)
|
||||
if (!input)
|
||||
keyPath = renderKeyPath L"\\" + deviceGuid;
|
||||
else
|
||||
keyPath = captureKeyPath L"\\" + deviceGuid;
|
||||
@@ -502,7 +507,7 @@ void DeviceAPOInfo::install()
|
||||
{
|
||||
if (selectedInstallState.installPreMix)
|
||||
RegistryHelper::writeValue(keyPath + L"\\FxProperties", lfxGuidValueName, RegistryHelper::getGuidString(EQUALIZERAPO_PRE_MIX_GUID));
|
||||
if (selectedInstallState.installPostMix && !isInput)
|
||||
if (selectedInstallState.installPostMix && !input)
|
||||
RegistryHelper::writeValue(keyPath + L"\\FxProperties", gfxGuidValueName, RegistryHelper::getGuidString(EQUALIZERAPO_POST_MIX_GUID));
|
||||
if (RegistryHelper::valueExists(keyPath + L"\\FxProperties", sfxGuidValueName))
|
||||
RegistryHelper::deleteValue(keyPath + L"\\FxProperties", sfxGuidValueName);
|
||||
@@ -523,7 +528,7 @@ void DeviceAPOInfo::install()
|
||||
if (!RegistryHelper::valueExists(keyPath + L"\\FxProperties", sfxProcessingModesValueName))
|
||||
RegistryHelper::writeMultiValue(keyPath + L"\\FxProperties", sfxProcessingModesValueName, defaultProcessingModeValue);
|
||||
}
|
||||
if (selectedInstallState.installPostMix && !isInput)
|
||||
if (selectedInstallState.installPostMix && !input)
|
||||
{
|
||||
RegistryHelper::writeValue(keyPath + L"\\FxProperties", mfxGuidValueName, RegistryHelper::getGuidString(EQUALIZERAPO_POST_MIX_GUID));
|
||||
if (!RegistryHelper::valueExists(keyPath + L"\\FxProperties", mfxProcessingModesValueName))
|
||||
@@ -544,7 +549,7 @@ void DeviceAPOInfo::install()
|
||||
RegistryHelper::writeMultiValue(keyPath + L"\\FxProperties", sfxProcessingModesValueName, defaultProcessingModeValue);
|
||||
}
|
||||
// don't change mfx
|
||||
if (selectedInstallState.installPostMix && !isInput)
|
||||
if (selectedInstallState.installPostMix && !input)
|
||||
{
|
||||
RegistryHelper::writeValue(keyPath + L"\\FxProperties", efxGuidValueName, RegistryHelper::getGuidString(EQUALIZERAPO_POST_MIX_GUID));
|
||||
if (!RegistryHelper::valueExists(keyPath + L"\\FxProperties", efxProcessingModesValueName))
|
||||
@@ -560,7 +565,7 @@ void DeviceAPOInfo::install()
|
||||
void DeviceAPOInfo::uninstall()
|
||||
{
|
||||
wstring keyPath;
|
||||
if (!isInput)
|
||||
if (!input)
|
||||
keyPath = renderKeyPath L"\\" + deviceGuid;
|
||||
else
|
||||
keyPath = captureKeyPath L"\\" + deviceGuid;
|
||||
@@ -594,3 +599,85 @@ void DeviceAPOInfo::uninstall()
|
||||
if (RegistryHelper::keyEmpty(childApoPath))
|
||||
RegistryHelper::deleteKey(childApoPath);
|
||||
}
|
||||
|
||||
void DeviceAPOInfo::reinstall()
|
||||
{
|
||||
uninstall();
|
||||
load(deviceGuid);
|
||||
install();
|
||||
}
|
||||
|
||||
wstring DeviceAPOInfo::getConnectionName() const
|
||||
{
|
||||
return connectionName;
|
||||
}
|
||||
|
||||
wstring DeviceAPOInfo::getDeviceName() const
|
||||
{
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
wstring DeviceAPOInfo::getDeviceGuid() const
|
||||
{
|
||||
return deviceGuid;
|
||||
}
|
||||
|
||||
wstring DeviceAPOInfo::getDeviceString() const
|
||||
{
|
||||
return getConnectionName() + L" " + getDeviceName() + L" " + getDeviceGuid();
|
||||
}
|
||||
|
||||
unsigned DeviceAPOInfo::getChannelCount() const
|
||||
{
|
||||
return channelCount;
|
||||
}
|
||||
|
||||
unsigned DeviceAPOInfo::getSampleRate() const
|
||||
{
|
||||
return sampleRate;
|
||||
}
|
||||
|
||||
unsigned long DeviceAPOInfo::getChannelMask() const
|
||||
{
|
||||
return channelMask;
|
||||
}
|
||||
|
||||
bool DeviceAPOInfo::isInput() const
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
bool DeviceAPOInfo::isInstalled() const
|
||||
{
|
||||
return installed;
|
||||
}
|
||||
|
||||
bool DeviceAPOInfo::isEnhancementsDisabled() const
|
||||
{
|
||||
return enhancementsDisabled;
|
||||
}
|
||||
|
||||
bool DeviceAPOInfo::isDefaultDevice() const
|
||||
{
|
||||
return defaultDevice;
|
||||
}
|
||||
|
||||
const DeviceAPOInfo::InstallState& DeviceAPOInfo::getCurrentInstallState()
|
||||
{
|
||||
return currentInstallState;
|
||||
}
|
||||
|
||||
DeviceAPOInfo::InstallState& DeviceAPOInfo::getSelectedInstallState()
|
||||
{
|
||||
return selectedInstallState;
|
||||
}
|
||||
|
||||
wstring DeviceAPOInfo::getPreMixChildGuid()
|
||||
{
|
||||
return preMixChildGuid;
|
||||
}
|
||||
|
||||
wstring DeviceAPOInfo::getPostMixChildGuid()
|
||||
{
|
||||
return postMixChildGuid;
|
||||
}
|
||||
+31
-12
@@ -21,12 +21,14 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "AbstractAPOInfo.h"
|
||||
|
||||
#define APOGUID_NULL L"{00000000-0000-0000-0000-000000000000}"
|
||||
#define APOGUID_NOKEY L"!KEY"
|
||||
#define APOGUID_NOVALUE L"!VALUE"
|
||||
|
||||
class DeviceAPOInfo
|
||||
class DeviceAPOInfo : public AbstractAPOInfo
|
||||
{
|
||||
public:
|
||||
enum InstallMode
|
||||
@@ -55,33 +57,50 @@ public:
|
||||
allowSilentBufferModification = false;
|
||||
}
|
||||
|
||||
bool operator!=(InstallState& other)
|
||||
bool operator!=(const InstallState& other) const
|
||||
{
|
||||
return memcmp(this, &other, sizeof(InstallState)) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
static std::vector<DeviceAPOInfo> loadAllInfos(bool input);
|
||||
static std::vector<std::shared_ptr<AbstractAPOInfo> > loadAllInfos(bool input);
|
||||
static std::wstring getDefaultDevice(bool input, int role = 1);
|
||||
static bool checkProtectedAudioDG(bool fix);
|
||||
static bool checkAPORegistration(bool fix);
|
||||
bool load(const std::wstring& deviceGuid, std::wstring defaultDeviceGuid = L"");
|
||||
bool canBeUpgraded();
|
||||
bool hasChanges();
|
||||
bool isExperimental();
|
||||
bool canBeUpgraded() const override;
|
||||
bool hasChanges() const override;
|
||||
bool isExperimental() const override;
|
||||
std::wstring getOriginalAPOPreMix();
|
||||
std::wstring getOriginalAPOPostMix();
|
||||
void install();
|
||||
void uninstall();
|
||||
void install() override;
|
||||
void uninstall() override;
|
||||
void reinstall() override;
|
||||
std::wstring getConnectionName() const override;
|
||||
std::wstring getDeviceName() const override;
|
||||
std::wstring getDeviceGuid() const override;
|
||||
std::wstring getDeviceString() const override;
|
||||
unsigned getChannelCount() const override;
|
||||
unsigned getSampleRate() const override;
|
||||
unsigned long getChannelMask() const override;
|
||||
bool isInput() const override;
|
||||
bool isInstalled() const override;
|
||||
bool isEnhancementsDisabled() const override;
|
||||
bool isDefaultDevice() const override;
|
||||
const InstallState& getCurrentInstallState();
|
||||
InstallState& getSelectedInstallState();
|
||||
std::wstring getPreMixChildGuid();
|
||||
std::wstring getPostMixChildGuid();
|
||||
|
||||
private:
|
||||
std::wstring deviceName;
|
||||
std::wstring connectionName;
|
||||
std::wstring deviceGuid;
|
||||
unsigned channelCount;
|
||||
unsigned sampleRate;
|
||||
unsigned long channelMask;
|
||||
bool isDefaultDevice;
|
||||
bool isEnhancementsDisabled;
|
||||
bool defaultDevice;
|
||||
bool enhancementsDisabled;
|
||||
|
||||
// used for creating child APO
|
||||
std::wstring preMixChildGuid;
|
||||
@@ -90,8 +109,8 @@ public:
|
||||
// used for uninstallation
|
||||
std::wstring originalApoGuids[5];
|
||||
|
||||
bool isInput;
|
||||
bool isInstalled;
|
||||
bool input;
|
||||
bool installed;
|
||||
std::wstring version;
|
||||
InstallState currentInstallState;
|
||||
// selection in GUI
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "FilterEngine.h"
|
||||
#include "AnalysisThread.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
AnalysisThread::AnalysisThread()
|
||||
{
|
||||
}
|
||||
@@ -50,10 +52,10 @@ AnalysisThread::~AnalysisThread()
|
||||
fftwf_destroy_plan(planForward);
|
||||
}
|
||||
|
||||
void AnalysisThread::setParameters(DeviceAPOInfo* device, int channelMask, int channelIndex, QString configPath, int frameCount)
|
||||
void AnalysisThread::setParameters(shared_ptr<AbstractAPOInfo> device, int channelMask, int channelIndex, QString configPath, int frameCount)
|
||||
{
|
||||
QMutexLocker mutexLocker(&mutex);
|
||||
this->device = *device;
|
||||
this->device = device;
|
||||
this->channelMask = channelMask;
|
||||
this->channelIndex = channelIndex;
|
||||
this->configPath = configPath;
|
||||
@@ -125,7 +127,7 @@ void AnalysisThread::run()
|
||||
break;
|
||||
}
|
||||
|
||||
DeviceAPOInfo device = this->device;
|
||||
shared_ptr<AbstractAPOInfo> device = this->device;
|
||||
int channelMask = this->channelMask;
|
||||
int channelIndex = this->channelIndex;
|
||||
QString configPath = this->configPath;
|
||||
@@ -136,8 +138,8 @@ void AnalysisThread::run()
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
|
||||
unsigned channelCount = device.channelCount;
|
||||
if (channelMask != 0 && channelMask != device.channelMask)
|
||||
unsigned channelCount = device->getChannelCount();
|
||||
if (channelMask != 0 && channelMask != device->getChannelMask())
|
||||
{
|
||||
channelCount = 0;
|
||||
for (int i = 0; i < 31; i++)
|
||||
@@ -148,11 +150,11 @@ void AnalysisThread::run()
|
||||
}
|
||||
}
|
||||
|
||||
unsigned sampleRate = device.sampleRate;
|
||||
unsigned sampleRate = device->getSampleRate();
|
||||
|
||||
qint64 startTime = timer.nsecsElapsed();
|
||||
FilterEngine engine;
|
||||
engine.setDeviceInfo(device.isInput, true, device.deviceName, device.connectionName, device.deviceGuid);
|
||||
engine.setDeviceInfo(device->isInput(), true, device->getDeviceName(), device->getConnectionName(), device->getDeviceGuid(), device->getDeviceString());
|
||||
engine.initialize(sampleRate, channelCount, channelCount, channelCount, channelMask, frameCount, configPath.toStdWString());
|
||||
double initializationTime = (timer.nsecsElapsed() - startTime) / 1e6;
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ class AnalysisThread : public QThread
|
||||
public:
|
||||
AnalysisThread();
|
||||
~AnalysisThread();
|
||||
void setParameters(DeviceAPOInfo* device, int channelMask, int channelIndex, QString configPath, int frameCount);
|
||||
void setParameters(std::shared_ptr<AbstractAPOInfo> device, int channelMask, int channelIndex, QString configPath, int frameCount);
|
||||
void beginGetResult();
|
||||
void endGetResult();
|
||||
|
||||
@@ -57,7 +57,7 @@ private:
|
||||
bool quit = false;
|
||||
|
||||
// input
|
||||
DeviceAPOInfo device;
|
||||
std::shared_ptr<AbstractAPOInfo> device;
|
||||
int channelMask;
|
||||
int channelIndex;
|
||||
QString configPath;
|
||||
|
||||
+8
-4
@@ -114,7 +114,9 @@ SOURCES += main.cpp\
|
||||
widgets/ExponentialSpinBox.cpp \
|
||||
FilterTableMimeData.cpp \
|
||||
helpers/DPIHelper.cpp \
|
||||
CustomStyle.cpp
|
||||
CustomStyle.cpp \
|
||||
../AbstractAPOInfo.cpp \
|
||||
../VoicemeeterAPOInfo.cpp
|
||||
|
||||
HEADERS += \
|
||||
../helpers/LogHelper.h \
|
||||
@@ -217,7 +219,9 @@ HEADERS += \
|
||||
widgets/ExponentialSpinBox.h \
|
||||
FilterTableMimeData.h \
|
||||
helpers/DPIHelper.h \
|
||||
CustomStyle.h
|
||||
CustomStyle.h \
|
||||
../AbstractAPOInfo.h \
|
||||
../VoicemeeterAPOInfo.h
|
||||
|
||||
FORMS += \
|
||||
guis/PreampFilterGUI.ui \
|
||||
@@ -238,7 +242,7 @@ FORMS += \
|
||||
guis/StageFilterGUI.ui
|
||||
|
||||
INCLUDEPATH += $$PWD/.. "C:/Program Files/libsndfile/include" "C:/Program Files/fftw3" "C:/Program Files/muparserx_v3_0_1/parser"
|
||||
LIBS += advapi32.lib version.lib ole32.lib Shlwapi.lib authz.lib libsndfile-1.lib libfftw3f-3.lib
|
||||
LIBS += user32.lib advapi32.lib version.lib ole32.lib Shlwapi.lib authz.lib libsndfile-1.lib libfftw3f-3.lib
|
||||
|
||||
build_pass:CONFIG(debug, debug|release) {
|
||||
LIBS += muparserxd.lib
|
||||
@@ -256,6 +260,6 @@ RESOURCES += \
|
||||
Editor.qrc
|
||||
TRANSLATIONS += translations/Editor_de.ts
|
||||
|
||||
RC_ICONS = icons/accessories-text-editor.ico
|
||||
RC_FILE = Editor.rc
|
||||
|
||||
DISTFILES += ../uncrustify.cfg
|
||||
@@ -0,0 +1,44 @@
|
||||
# if defined(UNDER_CE)
|
||||
# include <winbase.h>
|
||||
# else
|
||||
# include <windows.h>
|
||||
# endif
|
||||
#include "../version.h"
|
||||
|
||||
#define S2(x) #x
|
||||
#define S(x) S2(x)
|
||||
|
||||
IDI_ICON1 ICON DISCARDABLE "icons\\accessories-text-editor.ico"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION MAJOR,MINOR,REVISION,0
|
||||
PRODUCTVERSION MAJOR,MINOR,REVISION,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "Equalizer APO Configuration Editor\0"
|
||||
VALUE "FileVersion", S(MAJOR) "." S(MINOR) "." S(REVISION) ".0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2017\0"
|
||||
VALUE "OriginalFilename", "Editor.exe\0"
|
||||
VALUE "ProductName", "Configuration Editor\0"
|
||||
VALUE "ProductVersion", S(MAJOR) "." S(MINOR) "." S(REVISION) ".0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0409, 1200
|
||||
END
|
||||
END
|
||||
/* End of Version info */
|
||||
|
||||
@@ -83,7 +83,7 @@ FilterTable::FilterTable(MainWindow* mainWindow, QWidget* parent)
|
||||
QApplication::instance()->installEventFilter(this);
|
||||
}
|
||||
|
||||
void FilterTable::initialize(QScrollArea* scrollArea, const QList<DeviceAPOInfo>& outputDevices, const QList<DeviceAPOInfo>& inputDevices)
|
||||
void FilterTable::initialize(QScrollArea* scrollArea, const QList<shared_ptr<AbstractAPOInfo> >& outputDevices, const QList<shared_ptr<AbstractAPOInfo> >& inputDevices)
|
||||
{
|
||||
this->scrollArea = scrollArea;
|
||||
this->outputDevices = outputDevices;
|
||||
@@ -93,7 +93,7 @@ void FilterTable::initialize(QScrollArea* scrollArea, const QList<DeviceAPOInfo>
|
||||
factory->initialize(this);
|
||||
}
|
||||
|
||||
void FilterTable::updateDeviceAndChannelMask(DeviceAPOInfo* selectedDevice, int channelMask)
|
||||
void FilterTable::updateDeviceAndChannelMask(shared_ptr<AbstractAPOInfo> selectedDevice, int channelMask)
|
||||
{
|
||||
this->selectedDevice = selectedDevice;
|
||||
this->selectedChannelMask = channelMask;
|
||||
@@ -222,7 +222,9 @@ void FilterTable::updateGuis()
|
||||
|
||||
void FilterTable::propagateChannels()
|
||||
{
|
||||
vector<wstring> channelNames = ChannelHelper::getChannelNames(selectedDevice->channelCount, selectedChannelMask);
|
||||
vector<wstring> channelNames;
|
||||
if (selectedDevice != NULL)
|
||||
channelNames = ChannelHelper::getChannelNames(selectedDevice->getChannelCount(), selectedChannelMask);
|
||||
|
||||
for (Item* item : items)
|
||||
{
|
||||
@@ -1009,17 +1011,17 @@ const QSet<FilterTable::Item*>& FilterTable::getSelectedItems() const
|
||||
return selected;
|
||||
}
|
||||
|
||||
const QList<DeviceAPOInfo>& FilterTable::getOutputDevices() const
|
||||
const QList<shared_ptr<AbstractAPOInfo> >& FilterTable::getOutputDevices() const
|
||||
{
|
||||
return outputDevices;
|
||||
}
|
||||
|
||||
const QList<DeviceAPOInfo>& FilterTable::getInputDevices() const
|
||||
const QList<shared_ptr<AbstractAPOInfo> >& FilterTable::getInputDevices() const
|
||||
{
|
||||
return inputDevices;
|
||||
}
|
||||
|
||||
DeviceAPOInfo* FilterTable::getSelectedDevice() const
|
||||
shared_ptr<AbstractAPOInfo> FilterTable::getSelectedDevice() const
|
||||
{
|
||||
return selectedDevice;
|
||||
}
|
||||
|
||||
@@ -56,8 +56,8 @@ public:
|
||||
};
|
||||
|
||||
explicit FilterTable(MainWindow* mainWindow, QWidget* parent = 0);
|
||||
void initialize(QScrollArea* scrollArea, const QList<DeviceAPOInfo>& outputDevices, const QList<DeviceAPOInfo>& inputDevices);
|
||||
void updateDeviceAndChannelMask(DeviceAPOInfo* selectedDevice, int selectedChannelMask);
|
||||
void initialize(QScrollArea* scrollArea, const QList<std::shared_ptr<AbstractAPOInfo> >& outputDevices, const QList<std::shared_ptr<AbstractAPOInfo> >& inputDevices);
|
||||
void updateDeviceAndChannelMask(std::shared_ptr<AbstractAPOInfo> selectedDevice, int selectedChannelMask);
|
||||
void updateGuis();
|
||||
void propagateChannels();
|
||||
QList<QString> getLines();
|
||||
@@ -70,9 +70,9 @@ public:
|
||||
void paste();
|
||||
void deleteSelectedLines();
|
||||
|
||||
const QList<DeviceAPOInfo>& getOutputDevices() const;
|
||||
const QList<DeviceAPOInfo>& getInputDevices() const;
|
||||
DeviceAPOInfo* getSelectedDevice() const;
|
||||
const QList<std::shared_ptr<AbstractAPOInfo> >& getOutputDevices() const;
|
||||
const QList<std::shared_ptr<AbstractAPOInfo> >& getInputDevices() const;
|
||||
std::shared_ptr<AbstractAPOInfo> getSelectedDevice() const;
|
||||
int getSelectedChannelMask() const;
|
||||
|
||||
const QSet<Item*>& getSelectedItems() const;
|
||||
@@ -131,9 +131,9 @@ private:
|
||||
QList<IFilterGUIFactory*> factories;
|
||||
bool scrollingNow = false;
|
||||
QPoint scrollStartPoint;
|
||||
QList<DeviceAPOInfo> outputDevices;
|
||||
QList<DeviceAPOInfo> inputDevices;
|
||||
DeviceAPOInfo* selectedDevice;
|
||||
QList<std::shared_ptr<AbstractAPOInfo> > outputDevices;
|
||||
QList<std::shared_ptr<AbstractAPOInfo> > inputDevices;
|
||||
std::shared_ptr<AbstractAPOInfo> selectedDevice;
|
||||
int selectedChannelMask;
|
||||
QString configPath;
|
||||
int minimumHeightHint = 0;
|
||||
|
||||
+39
-39
@@ -51,15 +51,15 @@ using namespace std;
|
||||
MainWindow::MainWindow(QDir configDir, QWidget* parent)
|
||||
: QMainWindow(parent), ui(new Ui::MainWindow), configDir(configDir)
|
||||
{
|
||||
outputDevices = QList<DeviceAPOInfo>::fromVector(QVector<DeviceAPOInfo>::fromStdVector(DeviceAPOInfo::loadAllInfos(false)));
|
||||
inputDevices = QList<DeviceAPOInfo>::fromVector(QVector<DeviceAPOInfo>::fromStdVector(DeviceAPOInfo::loadAllInfos(true)));
|
||||
outputDevices = QList<shared_ptr<AbstractAPOInfo> >::fromVector(QVector<shared_ptr<AbstractAPOInfo> >::fromStdVector(DeviceAPOInfo::loadAllInfos(false)));
|
||||
inputDevices = QList<shared_ptr<AbstractAPOInfo> >::fromVector(QVector<shared_ptr<AbstractAPOInfo> >::fromStdVector(DeviceAPOInfo::loadAllInfos(true)));
|
||||
|
||||
defaultOutputDevice = NULL;
|
||||
for (DeviceAPOInfo& apoInfo : outputDevices)
|
||||
for (shared_ptr<AbstractAPOInfo>& apoInfo : outputDevices)
|
||||
{
|
||||
if (apoInfo.isDefaultDevice)
|
||||
if (apoInfo->isDefaultDevice())
|
||||
{
|
||||
defaultOutputDevice = &apoInfo;
|
||||
defaultOutputDevice = apoInfo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -106,7 +106,7 @@ MainWindow::MainWindow(QDir configDir, QWidget* parent)
|
||||
|
||||
QStandardItemModel* model = qobject_cast<QStandardItemModel*>(deviceComboBox->model());
|
||||
if (defaultOutputDevice != NULL)
|
||||
deviceComboBox->addItem(tr("Default") + " (" + QString::fromStdWString(defaultOutputDevice->connectionName) + " - " + QString::fromStdWString(defaultOutputDevice->deviceName) + ")", NULL);
|
||||
deviceComboBox->addItem(tr("Default") + " (" + QString::fromStdWString(defaultOutputDevice->getConnectionName()) + " - " + QString::fromStdWString(defaultOutputDevice->getDeviceName()) + ")", NULL);
|
||||
|
||||
deviceComboBox->addItem(tr("Playback devices:"));
|
||||
QStandardItem* item = model->item(model->rowCount() - 1);
|
||||
@@ -115,18 +115,18 @@ MainWindow::MainWindow(QDir configDir, QWidget* parent)
|
||||
item->setFont(font);
|
||||
item->setSelectable(false);
|
||||
|
||||
for (DeviceAPOInfo& apoInfo : outputDevices)
|
||||
if (apoInfo.isInstalled)
|
||||
deviceComboBox->addItem(QString::fromStdWString(apoInfo.connectionName) + " - " + QString::fromStdWString(apoInfo.deviceName), QVariant::fromValue(&apoInfo));
|
||||
for (shared_ptr<AbstractAPOInfo>& apoInfo : outputDevices)
|
||||
if (apoInfo->isInstalled())
|
||||
deviceComboBox->addItem(QString::fromStdWString(apoInfo->getConnectionName()) + " - " + QString::fromStdWString(apoInfo->getDeviceName()), QVariant::fromValue(apoInfo));
|
||||
|
||||
deviceComboBox->addItem(tr("Capture devices:"));
|
||||
item = model->item(model->rowCount() - 1);
|
||||
item->setFont(font);
|
||||
item->setSelectable(false);
|
||||
|
||||
for (DeviceAPOInfo& apoInfo : inputDevices)
|
||||
if (apoInfo.isInstalled)
|
||||
deviceComboBox->addItem(QString::fromStdWString(apoInfo.connectionName) + " - " + QString::fromStdWString(apoInfo.deviceName), QVariant::fromValue(&apoInfo));
|
||||
for (shared_ptr<AbstractAPOInfo>& apoInfo : inputDevices)
|
||||
if (apoInfo->isInstalled())
|
||||
deviceComboBox->addItem(QString::fromStdWString(apoInfo->getConnectionName()) + " - " + QString::fromStdWString(apoInfo->getDeviceName()), QVariant::fromValue(apoInfo));
|
||||
|
||||
connect(channelConfigurationComboBox, SIGNAL(activated(int)), this, SLOT(channelConfigurationSelected(int)));
|
||||
|
||||
@@ -183,7 +183,7 @@ void MainWindow::doChecks()
|
||||
}
|
||||
}
|
||||
|
||||
if (!defaultOutputDevice->isInstalled)
|
||||
if (defaultOutputDevice != NULL && !defaultOutputDevice->isInstalled())
|
||||
{
|
||||
if (QMessageBox::warning(this, tr("APO not installed to device"), tr("Equalizer APO has not been installed to the selected device.\nDo you want to run the Configurator application to fix the problem?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
|
||||
{
|
||||
@@ -192,23 +192,23 @@ void MainWindow::doChecks()
|
||||
}
|
||||
}
|
||||
|
||||
DeviceAPOInfo* disabledApoInfo = NULL;
|
||||
for (DeviceAPOInfo& apoInfo : outputDevices)
|
||||
AbstractAPOInfo* disabledApoInfo = NULL;
|
||||
for (shared_ptr<AbstractAPOInfo>& apoInfo : outputDevices)
|
||||
{
|
||||
if (apoInfo.isInstalled && apoInfo.isEnhancementsDisabled)
|
||||
if (apoInfo->isInstalled() && apoInfo->isEnhancementsDisabled())
|
||||
{
|
||||
disabledApoInfo = &apoInfo;
|
||||
disabledApoInfo = apoInfo.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (disabledApoInfo == NULL)
|
||||
{
|
||||
for (DeviceAPOInfo& apoInfo : inputDevices)
|
||||
for (shared_ptr<AbstractAPOInfo>& apoInfo : inputDevices)
|
||||
{
|
||||
if (apoInfo.isInstalled && apoInfo.isEnhancementsDisabled)
|
||||
if (apoInfo->isInstalled() && apoInfo->isEnhancementsDisabled())
|
||||
{
|
||||
disabledApoInfo = &apoInfo;
|
||||
disabledApoInfo = apoInfo.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -216,7 +216,7 @@ void MainWindow::doChecks()
|
||||
|
||||
if (disabledApoInfo != NULL)
|
||||
{
|
||||
if (QMessageBox::warning(this, tr("Audio enhancements disabled"), tr("Audio enhancements are not enabled for the device\n%0 %1.\nDo you want to run the Configurator application to fix the problem?").arg(QString::fromStdWString(disabledApoInfo->connectionName)).arg(QString::fromStdWString(disabledApoInfo->deviceName)), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
|
||||
if (QMessageBox::warning(this, tr("Audio enhancements disabled"), tr("Audio enhancements are not enabled for the device\n%0 %1.\nDo you want to run the Configurator application to fix the problem?").arg(QString::fromStdWString(disabledApoInfo->getConnectionName())).arg(QString::fromStdWString(disabledApoInfo->getDeviceName())), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
|
||||
{
|
||||
runConfigurator();
|
||||
return;
|
||||
@@ -402,7 +402,7 @@ void MainWindow::closeEvent(QCloseEvent* event)
|
||||
|
||||
void MainWindow::deviceSelected(int index)
|
||||
{
|
||||
DeviceAPOInfo* apoInfo = deviceComboBox->itemData(index).value<DeviceAPOInfo*>();
|
||||
shared_ptr<AbstractAPOInfo> apoInfo = deviceComboBox->itemData(index).value<shared_ptr<AbstractAPOInfo> >();
|
||||
if (apoInfo == NULL)
|
||||
apoInfo = defaultOutputDevice;
|
||||
|
||||
@@ -415,7 +415,7 @@ void MainWindow::deviceSelected(int index)
|
||||
const GUIChannelHelper::ChannelConfigurationInfo* selectedInfo = NULL;
|
||||
for (const GUIChannelHelper::ChannelConfigurationInfo& info : infos)
|
||||
{
|
||||
if (info.channelMask == apoInfo->channelMask)
|
||||
if (info.channelMask == apoInfo->getChannelMask())
|
||||
{
|
||||
selectedInfo = &info;
|
||||
break;
|
||||
@@ -425,7 +425,7 @@ void MainWindow::deviceSelected(int index)
|
||||
if (selectedInfo != NULL)
|
||||
channelConfigurationComboBox->addItem(tr("From device") + " (" + selectedInfo->name + ")", 0);
|
||||
else
|
||||
channelConfigurationComboBox->addItem(tr("From device") + " (" + apoInfo->channelCount + " channels)", 0);
|
||||
channelConfigurationComboBox->addItem(tr("From device") + " (" + apoInfo->getChannelCount() + " channels)", 0);
|
||||
}
|
||||
|
||||
for (const GUIChannelHelper::ChannelConfigurationInfo& info : infos)
|
||||
@@ -436,7 +436,7 @@ void MainWindow::deviceSelected(int index)
|
||||
|
||||
void MainWindow::channelConfigurationSelected(int index)
|
||||
{
|
||||
DeviceAPOInfo* selectedDevice;
|
||||
shared_ptr<AbstractAPOInfo> selectedDevice;
|
||||
int channelMask;
|
||||
getDeviceAndChannelMask(&selectedDevice, &channelMask);
|
||||
|
||||
@@ -451,8 +451,8 @@ void MainWindow::channelConfigurationSelected(int index)
|
||||
|
||||
if (selectedDevice != NULL)
|
||||
{
|
||||
unsigned channelCount = selectedDevice->channelCount;
|
||||
if (channelMask != 0 && channelMask != selectedDevice->channelMask)
|
||||
unsigned channelCount = selectedDevice->getChannelCount();
|
||||
if (channelMask != 0 && channelMask != selectedDevice->getChannelMask())
|
||||
{
|
||||
channelCount = 0;
|
||||
for (int i = 0; i < 31; i++)
|
||||
@@ -816,7 +816,7 @@ FilterTable* MainWindow::addTab(QString title, QString tooltip, QString configPa
|
||||
filterTable->setAcceptDrops(true);
|
||||
filterTable->setFocusPolicy(Qt::WheelFocus);
|
||||
|
||||
DeviceAPOInfo* selectedDevice;
|
||||
shared_ptr<AbstractAPOInfo> selectedDevice;
|
||||
int channelMask;
|
||||
getDeviceAndChannelMask(&selectedDevice, &channelMask);
|
||||
filterTable->updateDeviceAndChannelMask(selectedDevice, channelMask);
|
||||
@@ -829,19 +829,19 @@ FilterTable* MainWindow::addTab(QString title, QString tooltip, QString configPa
|
||||
return filterTable;
|
||||
}
|
||||
|
||||
void MainWindow::getDeviceAndChannelMask(DeviceAPOInfo** selectedDevice, int* channelMask)
|
||||
void MainWindow::getDeviceAndChannelMask(shared_ptr<AbstractAPOInfo>* selectedDevice, int* channelMask)
|
||||
{
|
||||
*selectedDevice = deviceComboBox->currentData().value<DeviceAPOInfo*>();
|
||||
*selectedDevice = deviceComboBox->currentData().value<shared_ptr<AbstractAPOInfo> >();
|
||||
if (*selectedDevice == NULL)
|
||||
*selectedDevice = defaultOutputDevice;
|
||||
|
||||
*channelMask = channelConfigurationComboBox->currentData().toInt();
|
||||
if (*channelMask == 0 && selectedDevice != NULL)
|
||||
{
|
||||
*channelMask = (*selectedDevice)->channelMask;
|
||||
*channelMask = (*selectedDevice)->getChannelMask();
|
||||
|
||||
if (*channelMask == 0)
|
||||
*channelMask = ChannelHelper::getDefaultChannelMask((*selectedDevice)->channelCount);
|
||||
*channelMask = ChannelHelper::getDefaultChannelMask((*selectedDevice)->getChannelCount());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -894,7 +894,7 @@ bool MainWindow::askForClose(int tabIndex)
|
||||
|
||||
void MainWindow::startAnalysis()
|
||||
{
|
||||
DeviceAPOInfo* selectedDevice;
|
||||
shared_ptr<AbstractAPOInfo> selectedDevice;
|
||||
|
||||
int channelMask;
|
||||
getDeviceAndChannelMask(&selectedDevice, &channelMask);
|
||||
@@ -933,15 +933,15 @@ void MainWindow::loadPreferences()
|
||||
if (stateValue.isValid())
|
||||
restoreState(stateValue.toByteArray());
|
||||
instantModeCheckBox->setChecked(settings.value("instantMode", true).toBool());
|
||||
QString selectedDeviceGuid = settings.value("selectedDeviceGuid").toString();
|
||||
if (!selectedDeviceGuid.isEmpty())
|
||||
QString selectedDevice = settings.value("selectedDevice").toString();
|
||||
if (!selectedDevice.isEmpty())
|
||||
{
|
||||
for (int i = 0; i < deviceComboBox->count(); i++)
|
||||
{
|
||||
DeviceAPOInfo* apoInfo = deviceComboBox->itemData(i).value<DeviceAPOInfo*>();
|
||||
shared_ptr<AbstractAPOInfo> apoInfo = deviceComboBox->itemData(i).value<shared_ptr<AbstractAPOInfo> >();
|
||||
if (apoInfo != NULL)
|
||||
{
|
||||
if (QString::fromStdWString(apoInfo->deviceGuid).compare(selectedDeviceGuid, Qt::CaseInsensitive) == 0)
|
||||
if (QString::fromStdWString(apoInfo->getDeviceString()).compare(selectedDevice, Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
deviceComboBox->setCurrentIndex(i);
|
||||
break;
|
||||
@@ -1012,8 +1012,8 @@ void MainWindow::savePreferences()
|
||||
settings.setValue("geometry", saveGeometry());
|
||||
settings.setValue("windowState", saveState());
|
||||
settings.setValue("instantMode", instantModeCheckBox->isChecked());
|
||||
DeviceAPOInfo* selectedDevice = deviceComboBox->currentData().value<DeviceAPOInfo*>();
|
||||
settings.setValue("selectedDeviceGuid", selectedDevice != NULL ? QString::fromStdWString(selectedDevice->deviceGuid) : "");
|
||||
shared_ptr<AbstractAPOInfo> selectedDevice = deviceComboBox->currentData().value<shared_ptr<AbstractAPOInfo> >();
|
||||
settings.setValue("selectedDevice", selectedDevice != NULL ? QString::fromStdWString(selectedDevice->getDeviceString()) : "");
|
||||
int channelMask = channelConfigurationComboBox->currentData().toInt();
|
||||
settings.setValue("selectedChannelMask", channelMask);
|
||||
|
||||
|
||||
+5
-5
@@ -91,7 +91,7 @@ private slots:
|
||||
|
||||
private:
|
||||
FilterTable* addTab(QString title, QString tooltip, QString configPath, QList<QString> lines);
|
||||
void getDeviceAndChannelMask(DeviceAPOInfo** selectedDevice, int* channelMask);
|
||||
void getDeviceAndChannelMask(std::shared_ptr<AbstractAPOInfo>* selectedDevice, int* channelMask);
|
||||
bool askForClose(int tabIndex);
|
||||
void startAnalysis();
|
||||
void loadPreferences();
|
||||
@@ -104,9 +104,9 @@ private:
|
||||
QCheckBox* instantModeCheckBox;
|
||||
QComboBox* deviceComboBox;
|
||||
QComboBox* channelConfigurationComboBox;
|
||||
QList<DeviceAPOInfo> outputDevices;
|
||||
QList<DeviceAPOInfo> inputDevices;
|
||||
DeviceAPOInfo* defaultOutputDevice;
|
||||
QList<std::shared_ptr<AbstractAPOInfo> > outputDevices;
|
||||
QList<std::shared_ptr<AbstractAPOInfo> > inputDevices;
|
||||
std::shared_ptr<AbstractAPOInfo> defaultOutputDevice;
|
||||
AnalysisPlotScene* analysisPlotScene;
|
||||
AnalysisThread* analysisThread;
|
||||
bool restart = false;
|
||||
@@ -115,4 +115,4 @@ private:
|
||||
QStringList recentFiles;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(DeviceAPOInfo*)
|
||||
Q_DECLARE_METATYPE(std::shared_ptr<AbstractAPOInfo>)
|
||||
@@ -22,13 +22,19 @@
|
||||
#include "ConvolutionFilterGUI.h"
|
||||
#include "ConvolutionFilterGUIFactory.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
ConvolutionFilterGUIFactory::ConvolutionFilterGUIFactory()
|
||||
{
|
||||
}
|
||||
|
||||
void ConvolutionFilterGUIFactory::initialize(FilterTable* filterTable)
|
||||
{
|
||||
deviceSampleRate = filterTable->getSelectedDevice()->sampleRate;
|
||||
shared_ptr<AbstractAPOInfo> selectedDevice = filterTable->getSelectedDevice();
|
||||
if (selectedDevice != NULL)
|
||||
deviceSampleRate = filterTable->getSelectedDevice()->getSampleRate();
|
||||
else
|
||||
deviceSampleRate = 0;
|
||||
}
|
||||
|
||||
QList<FilterTemplate> ConvolutionFilterGUIFactory::createFilterTemplates()
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "DeviceFilterGUI.h"
|
||||
#include "DeviceFilterGUIDialog.h"
|
||||
#include <filters/DeviceFilterFactory.h>
|
||||
#include <VoicemeeterAPOInfo.h>
|
||||
#include "ui_DeviceFilterGUI.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -63,27 +64,39 @@ void DeviceFilterGUI::load(const QString& parameters)
|
||||
}
|
||||
else
|
||||
{
|
||||
const QList<DeviceAPOInfo>& devices = factory->getDevices();
|
||||
for (const DeviceAPOInfo& apoInfo : devices)
|
||||
const QList<shared_ptr<AbstractAPOInfo> >& devices = factory->getDevices();
|
||||
bool anyInstalled = false;
|
||||
for (const shared_ptr<AbstractAPOInfo>& apoInfo : devices)
|
||||
{
|
||||
if (!apoInfo.isInstalled)
|
||||
if (apoInfo->isInstalled() && DeviceFilterFactory::matchDevice(apoInfo->getDeviceString(), pattern.toStdWString()))
|
||||
{
|
||||
anyInstalled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (const shared_ptr<AbstractAPOInfo>& apoInfo : devices)
|
||||
{
|
||||
if (anyInstalled && !apoInfo->isInstalled())
|
||||
continue;
|
||||
|
||||
wstring deviceString = apoInfo.connectionName + L" " + apoInfo.deviceName + L" " + apoInfo.deviceGuid;
|
||||
if (DeviceFilterFactory::matchDevice(deviceString, pattern.toStdWString()))
|
||||
if (DeviceFilterFactory::matchDevice(apoInfo->getDeviceString(), pattern.toStdWString()))
|
||||
{
|
||||
QStringList values;
|
||||
if (apoInfo.isInput)
|
||||
if (apoInfo->isInput())
|
||||
values.append(tr("Capture"));
|
||||
else
|
||||
values.append(tr("Playback"));
|
||||
values.append(QString::fromStdWString(apoInfo.connectionName));
|
||||
values.append(QString::fromStdWString(apoInfo.deviceName));
|
||||
values.append(QString::fromStdWString(apoInfo->getConnectionName()));
|
||||
values.append(QString::fromStdWString(apoInfo->getDeviceName()));
|
||||
QString state;
|
||||
if (apoInfo.isInstalled)
|
||||
if (apoInfo->isInstalled())
|
||||
state = tr("APO installed");
|
||||
else
|
||||
state = tr("APO not installed");
|
||||
VoicemeeterAPOInfo* voicemeeterInfo = dynamic_cast<VoicemeeterAPOInfo*>(apoInfo.get());
|
||||
if (voicemeeterInfo != NULL && !voicemeeterInfo->isVoicemeeterInstalled())
|
||||
state += ", " + tr("Voicemeeter was uninstalled");
|
||||
values.append(state);
|
||||
lastItem = new QTreeWidgetItem(ui->treeWidget, values);
|
||||
}
|
||||
@@ -93,7 +106,7 @@ void DeviceFilterGUI::load(const QString& parameters)
|
||||
{
|
||||
QStringList values;
|
||||
values.append("");
|
||||
values.append(tr("No device matched!"));
|
||||
values.append(tr("No device matched") + " \"" + pattern.trimmed() + "\"");
|
||||
values.append("");
|
||||
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(ui->treeWidget, values);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "ui_DeviceFilterGUIDialog.h"
|
||||
|
||||
#include <filters/DeviceFilterFactory.h>
|
||||
#include <VoicemeeterAPOInfo.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -44,26 +45,28 @@ DeviceFilterGUIDialog::DeviceFilterGUIDialog(DeviceFilterGUI* gui, DeviceFilterG
|
||||
outputNode->setExpanded(true);
|
||||
QTreeWidgetItem* inputNode = new QTreeWidgetItem(ui->treeWidget, QStringList(tr("Capture devices")));
|
||||
inputNode->setExpanded(true);
|
||||
const QList<DeviceAPOInfo>& devices = factory->getDevices();
|
||||
for (const DeviceAPOInfo& apoInfo : devices)
|
||||
const QList<shared_ptr<AbstractAPOInfo> >& devices = factory->getDevices();
|
||||
for (const shared_ptr<AbstractAPOInfo>& apoInfo : devices)
|
||||
{
|
||||
QStringList values;
|
||||
values.append(QString::fromStdWString(apoInfo.connectionName));
|
||||
values.append(QString::fromStdWString(apoInfo.deviceName));
|
||||
values.append(QString::fromStdWString(apoInfo->getConnectionName()));
|
||||
values.append(QString::fromStdWString(apoInfo->getDeviceName()));
|
||||
QString state;
|
||||
if (apoInfo.isInstalled)
|
||||
if (apoInfo->isInstalled())
|
||||
state = tr("APO installed");
|
||||
else
|
||||
state = tr("APO not installed");
|
||||
VoicemeeterAPOInfo* voicemeeterInfo = dynamic_cast<VoicemeeterAPOInfo*>(apoInfo.get());
|
||||
if (voicemeeterInfo != NULL && !voicemeeterInfo->isVoicemeeterInstalled())
|
||||
state += ", " + tr("Voicemeeter was uninstalled");
|
||||
values.append(state);
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(apoInfo.isInput ? inputNode : outputNode, values);
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(apoInfo->isInput() ? inputNode : outputNode, values);
|
||||
|
||||
wstring deviceString = apoInfo.connectionName + L" " + apoInfo.deviceName + L" " + apoInfo.deviceGuid;
|
||||
bool matches = !all && DeviceFilterFactory::matchDevice(deviceString, pattern.toStdWString());
|
||||
bool matches = !all && DeviceFilterFactory::matchDevice(apoInfo->getDeviceString(), pattern.toStdWString());
|
||||
item->setCheckState(0, matches ? Qt::Checked : Qt::Unchecked);
|
||||
item->setData(0, Qt::UserRole, QVariant::fromValue(&apoInfo));
|
||||
item->setHidden(!matches && !apoInfo.isInstalled && ui->showOnlyInstalledCheckBox->isChecked());
|
||||
if (!apoInfo.isInstalled)
|
||||
item->setData(0, Qt::UserRole, QVariant::fromValue(apoInfo));
|
||||
item->setHidden(!matches && !apoInfo->isInstalled() && ui->showOnlyInstalledCheckBox->isChecked());
|
||||
if (!apoInfo->isInstalled())
|
||||
for (int i = 0; i < ui->treeWidget->columnCount(); i++)
|
||||
item->setForeground(i, QBrush(Qt::gray));
|
||||
}
|
||||
@@ -96,9 +99,8 @@ QString DeviceFilterGUIDialog::getPattern()
|
||||
{
|
||||
if (pattern != "")
|
||||
pattern += "; ";
|
||||
const DeviceAPOInfo* apoInfo = item->data(0, Qt::UserRole).value<const DeviceAPOInfo*>();
|
||||
wstring deviceString = apoInfo->connectionName + L" " + apoInfo->deviceName + L" " + apoInfo->deviceGuid;
|
||||
pattern += QString::fromStdWString(deviceString);
|
||||
shared_ptr<AbstractAPOInfo> apoInfo = item->data(0, Qt::UserRole).value<shared_ptr<AbstractAPOInfo> >();
|
||||
pattern += QString::fromStdWString(apoInfo->getDeviceString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,8 +122,8 @@ void DeviceFilterGUIDialog::on_showOnlyInstalledCheckBox_toggled(bool checked)
|
||||
for (int j = 0; j < groupItem->childCount(); j++)
|
||||
{
|
||||
QTreeWidgetItem* item = groupItem->child(j);
|
||||
const DeviceAPOInfo* apoInfo = item->data(0, Qt::UserRole).value<const DeviceAPOInfo*>();
|
||||
item->setHidden(item->checkState(0) != Qt::Checked && !apoInfo->isInstalled && checked);
|
||||
shared_ptr<AbstractAPOInfo> apoInfo = item->data(0, Qt::UserRole).value<shared_ptr<AbstractAPOInfo> >();
|
||||
item->setHidden(item->checkState(0) != Qt::Checked && !apoInfo->isInstalled() && checked);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,4 +47,4 @@ private:
|
||||
Ui::DeviceFilterGUIDialog* ui;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(const DeviceAPOInfo*)
|
||||
Q_DECLARE_METATYPE(std::shared_ptr<AbstractAPOInfo>)
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "DeviceFilterGUI.h"
|
||||
#include "DeviceFilterGUIFactory.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
DeviceFilterGUIFactory::DeviceFilterGUIFactory()
|
||||
{
|
||||
}
|
||||
@@ -51,7 +53,7 @@ IFilterGUI* DeviceFilterGUIFactory::createFilterGUI(QString& command, QString& p
|
||||
return result;
|
||||
}
|
||||
|
||||
const QList<DeviceAPOInfo>& DeviceFilterGUIFactory::getDevices() const
|
||||
const QList<shared_ptr<AbstractAPOInfo> >& DeviceFilterGUIFactory::getDevices() const
|
||||
{
|
||||
return devices;
|
||||
}
|
||||
@@ -34,8 +34,8 @@ public:
|
||||
QList<FilterTemplate> createFilterTemplates() override;
|
||||
IFilterGUI* createFilterGUI(QString& command, QString& parameters) override;
|
||||
|
||||
const QList<DeviceAPOInfo>& getDevices() const;
|
||||
const QList<std::shared_ptr<AbstractAPOInfo> >& getDevices() const;
|
||||
|
||||
private:
|
||||
QList<DeviceAPOInfo> devices;
|
||||
QList<std::shared_ptr<AbstractAPOInfo> > devices;
|
||||
};
|
||||
Binary file not shown.
@@ -354,12 +354,12 @@ Wählen Sie eine andere Datei oder ändern Sie die Konfiguration des Geräts.</t
|
||||
<translation type="vanished">Convolution (Faltung mit Impulsantwort)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/ConvolutionFilterGUIFactory.cpp" line="37"/>
|
||||
<location filename="../guis/ConvolutionFilterGUIFactory.cpp" line="43"/>
|
||||
<source>Advanced filters</source>
|
||||
<translation>Fortgeschrittene Filter</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/ConvolutionFilterGUIFactory.cpp" line="37"/>
|
||||
<location filename="../guis/ConvolutionFilterGUIFactory.cpp" line="43"/>
|
||||
<source>Convolution (Convolution with impulse response)</source>
|
||||
<translation>Convolution (Faltung mit Impulsantwort)</translation>
|
||||
</message>
|
||||
@@ -524,54 +524,63 @@ Wählen Sie eine andere Datei oder ändern Sie die Konfiguration des Geräts.</t
|
||||
<translation>Ändern...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="47"/>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="48"/>
|
||||
<source>Type</source>
|
||||
<translation>Typ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="48"/>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="49"/>
|
||||
<source>Connection</source>
|
||||
<translation>Anschluss</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="49"/>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="50"/>
|
||||
<source>Device</source>
|
||||
<translation>Gerät</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="50"/>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="51"/>
|
||||
<source>State</source>
|
||||
<translation>Status</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="59"/>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="60"/>
|
||||
<source>All devices</source>
|
||||
<translation>Alle Geräte</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="77"/>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="87"/>
|
||||
<source>Capture</source>
|
||||
<translation>Aufnahme</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="79"/>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="89"/>
|
||||
<source>Playback</source>
|
||||
<translation>Wiedergabe</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="84"/>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="94"/>
|
||||
<source>APO installed</source>
|
||||
<translation>APO installiert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="86"/>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="96"/>
|
||||
<source>APO not installed</source>
|
||||
<translation>APO nicht installiert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="96"/>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="99"/>
|
||||
<source>Voicemeeter was uninstalled</source>
|
||||
<translation>Voicemeeter wurde deinstalliert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUI.cpp" line="109"/>
|
||||
<source>No device matched</source>
|
||||
<translation>Kein Gerät passt zu</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No device matched!</source>
|
||||
<translation>Kein Gerät stimmt überein!</translation>
|
||||
<translation type="vanished">Kein Gerät stimmt überein!</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@@ -592,40 +601,45 @@ Wählen Sie eine andere Datei oder ändern Sie die Konfiguration des Geräts.</t
|
||||
<translation>Nur Geräte mit installiertem APO zeigen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUIDialog.cpp" line="39"/>
|
||||
<location filename="../guis/DeviceFilterGUIDialog.cpp" line="40"/>
|
||||
<source>Connection</source>
|
||||
<translation>Anschluss</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUIDialog.cpp" line="40"/>
|
||||
<location filename="../guis/DeviceFilterGUIDialog.cpp" line="41"/>
|
||||
<source>Device</source>
|
||||
<translation>Gerät</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUIDialog.cpp" line="41"/>
|
||||
<location filename="../guis/DeviceFilterGUIDialog.cpp" line="42"/>
|
||||
<source>State</source>
|
||||
<translation>Status</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUIDialog.cpp" line="43"/>
|
||||
<location filename="../guis/DeviceFilterGUIDialog.cpp" line="44"/>
|
||||
<source>Playback devices</source>
|
||||
<translation>Wiedergabegeräte</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUIDialog.cpp" line="45"/>
|
||||
<location filename="../guis/DeviceFilterGUIDialog.cpp" line="46"/>
|
||||
<source>Capture devices</source>
|
||||
<translation>Aufnahmegeräte</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUIDialog.cpp" line="55"/>
|
||||
<location filename="../guis/DeviceFilterGUIDialog.cpp" line="56"/>
|
||||
<source>APO installed</source>
|
||||
<translation>APO installiert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUIDialog.cpp" line="57"/>
|
||||
<location filename="../guis/DeviceFilterGUIDialog.cpp" line="58"/>
|
||||
<source>APO not installed</source>
|
||||
<translation>APO nicht installiert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUIDialog.cpp" line="61"/>
|
||||
<source>Voicemeeter was uninstalled</source>
|
||||
<translation>Voicemeeter wurde deinstalliert</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DeviceFilterGUIFactory</name>
|
||||
@@ -634,12 +648,12 @@ Wählen Sie eine andere Datei oder ändern Sie die Konfiguration des Geräts.</t
|
||||
<translation type="vanished">Device (Gerät auswählen)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUIFactory.cpp" line="37"/>
|
||||
<location filename="../guis/DeviceFilterGUIFactory.cpp" line="39"/>
|
||||
<source>Control</source>
|
||||
<translation>Steuerung</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/DeviceFilterGUIFactory.cpp" line="37"/>
|
||||
<location filename="../guis/DeviceFilterGUIFactory.cpp" line="39"/>
|
||||
<source>Device (Select device)</source>
|
||||
<translation>Device (Gerät auswählen)</translation>
|
||||
</message>
|
||||
|
||||
+4
-4
@@ -138,14 +138,14 @@ HRESULT EqualizerAPO::Initialize(UINT32 cbDataSize, BYTE* pbyData)
|
||||
DeviceAPOInfo apoInfo;
|
||||
if (apoInfo.load(deviceGuid))
|
||||
{
|
||||
engine.setDeviceInfo(apoInfo.isInput, apoInfo.currentInstallState.installPostMix, apoInfo.deviceName, apoInfo.connectionName, apoInfo.deviceGuid);
|
||||
engine.setDeviceInfo(apoInfo.isInput(), apoInfo.getCurrentInstallState().installPostMix, apoInfo.getDeviceName(), apoInfo.getConnectionName(), apoInfo.getDeviceGuid(), apoInfo.getDeviceString());
|
||||
|
||||
if (apoGuid == EQUALIZERAPO_PRE_MIX_GUID)
|
||||
childApoGuid = apoInfo.preMixChildGuid;
|
||||
childApoGuid = apoInfo.getPreMixChildGuid();
|
||||
else
|
||||
childApoGuid = apoInfo.postMixChildGuid;
|
||||
childApoGuid = apoInfo.getPostMixChildGuid();
|
||||
|
||||
allowSilentBufferModification = apoInfo.currentInstallState.allowSilentBufferModification;
|
||||
allowSilentBufferModification = apoInfo.getCurrentInstallState().allowSilentBufferModification;
|
||||
}
|
||||
}
|
||||
catch (RegistryException e)
|
||||
|
||||
Binary file not shown.
@@ -12,6 +12,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Configurator", "Configurato
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Benchmark", "Benchmark\Benchmark.vcxproj", "{D4474852-5724-4253-95C6-7A6DC424F194}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VoicemeeterClient", "VoicemeeterClient\VoicemeeterClient.vcxproj", "{10F1DD37-EA50-46C2-810D-D01A1A0D4D2F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
@@ -44,6 +46,14 @@ Global
|
||||
{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
|
||||
{10F1DD37-EA50-46C2-810D-D01A1A0D4D2F}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{10F1DD37-EA50-46C2-810D-D01A1A0D4D2F}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{10F1DD37-EA50-46C2-810D-D01A1A0D4D2F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{10F1DD37-EA50-46C2-810D-D01A1A0D4D2F}.Debug|x64.Build.0 = Debug|x64
|
||||
{10F1DD37-EA50-46C2-810D-D01A1A0D4D2F}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{10F1DD37-EA50-46C2-810D-D01A1A0D4D2F}.Release|Win32.Build.0 = Release|Win32
|
||||
{10F1DD37-EA50-46C2-810D-D01A1A0D4D2F}.Release|x64.ActiveCfg = Release|x64
|
||||
{10F1DD37-EA50-46C2-810D-D01A1A0D4D2F}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -162,6 +162,7 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AbstractAPOInfo.h" />
|
||||
<ClInclude Include="ClassFactory.h" />
|
||||
<ClInclude Include="DeviceAPOInfo.h" />
|
||||
<ClInclude Include="EqualizerAPO.h" />
|
||||
@@ -195,7 +196,9 @@
|
||||
<ClInclude Include="helpers\MemoryHelper.h" />
|
||||
<ClInclude Include="helpers\PrecisionTimer.h" />
|
||||
<ClInclude Include="helpers\RegistryHelper.h" />
|
||||
<ClInclude Include="helpers\ScopeGuard.h" />
|
||||
<ClInclude Include="helpers\StringHelper.h" />
|
||||
<ClInclude Include="helpers\UncaughtExceptions.h" />
|
||||
<ClInclude Include="IFilter.h" />
|
||||
<ClInclude Include="IFilterFactory.h" />
|
||||
<ClInclude Include="libHybridConv-0.1.1\libHybridConv_eapo.h" />
|
||||
@@ -205,8 +208,10 @@
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="version.h" />
|
||||
<ClInclude Include="VoicemeeterAPOInfo.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AbstractAPOInfo.cpp" />
|
||||
<ClCompile Include="ClassFactory.cpp" />
|
||||
<ClCompile Include="DeviceAPOInfo.cpp" />
|
||||
<ClCompile Include="DllMain.cpp" />
|
||||
@@ -252,6 +257,7 @@
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VoicemeeterAPOInfo.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="EqualizerAPO.def" />
|
||||
|
||||
@@ -105,6 +105,8 @@
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
<ClCompile Include="AbstractAPOInfo.cpp" />
|
||||
<ClCompile Include="VoicemeeterAPOInfo.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ClassFactory.h" />
|
||||
@@ -216,6 +218,14 @@
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="AbstractAPOInfo.h" />
|
||||
<ClInclude Include="helpers\ScopeGuard.h">
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="helpers\UncaughtExceptions.h">
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VoicemeeterAPOInfo.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="EqualizerAPO.rc" />
|
||||
|
||||
Binary file not shown.
+36
-1
@@ -75,7 +75,7 @@ FilterConfiguration::~FilterConfiguration()
|
||||
}
|
||||
|
||||
#pragma AVRT_CODE_BEGIN
|
||||
void FilterConfiguration::process(float* input, unsigned frameCount)
|
||||
void FilterConfiguration::read(float* input, unsigned frameCount)
|
||||
{
|
||||
#define DEINTERLEAVE_MACRO(ccount)\
|
||||
{\
|
||||
@@ -107,7 +107,16 @@ void FilterConfiguration::process(float* input, unsigned frameCount)
|
||||
default:
|
||||
DEINTERLEAVE_MACRO(realChannelCount)
|
||||
}
|
||||
}
|
||||
|
||||
void FilterConfiguration::read(float** input, unsigned frameCount)
|
||||
{
|
||||
for (unsigned c = 0; c < realChannelCount; c++)
|
||||
memcpy(allSamples[c], input[c], frameCount * sizeof(float));
|
||||
}
|
||||
|
||||
void FilterConfiguration::process(unsigned frameCount)
|
||||
{
|
||||
for (unsigned c = realChannelCount; c < allChannelCount; c++)
|
||||
memset(allSamples[c], 0, frameCount * sizeof(float));
|
||||
|
||||
@@ -142,6 +151,26 @@ void FilterConfiguration::process(float* input, unsigned frameCount)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned FilterConfiguration::doTransition(FilterConfiguration* nextConfig, unsigned frameCount, unsigned transitionCounter, unsigned transitionLength)
|
||||
{
|
||||
float** currentSamples = allSamples;
|
||||
float** nextSamples = nextConfig->allSamples;
|
||||
|
||||
for (unsigned f = 0; f < frameCount; f++)
|
||||
{
|
||||
float factor = 0.5f * (1.0f - cos(transitionCounter * (float)M_PI / transitionLength));
|
||||
if (transitionCounter >= transitionLength)
|
||||
factor = 1.0f;
|
||||
|
||||
for (unsigned c = 0; c < outputChannelCount; c++)
|
||||
currentSamples[c][f] = currentSamples[c][f] * (1 - factor) + nextSamples[c][f] * factor;
|
||||
|
||||
transitionCounter++;
|
||||
}
|
||||
|
||||
return transitionCounter;
|
||||
}
|
||||
|
||||
void FilterConfiguration::write(float* output, unsigned frameCount)
|
||||
{
|
||||
#define INTERLEAVE_MACRO(ccount)\
|
||||
@@ -173,6 +202,12 @@ void FilterConfiguration::write(float* output, unsigned frameCount)
|
||||
INTERLEAVE_MACRO(outputChannelCount)
|
||||
}
|
||||
}
|
||||
|
||||
void FilterConfiguration::write(float** output, unsigned frameCount)
|
||||
{
|
||||
for (unsigned i = 0; i < outputChannelCount; i++)
|
||||
memcpy(output[i], allSamples[i], frameCount * sizeof(float));
|
||||
}
|
||||
#pragma AVRT_CODE_END
|
||||
|
||||
bool FilterConfiguration::isEmpty()
|
||||
|
||||
@@ -43,8 +43,12 @@ public:
|
||||
FilterConfiguration(FilterEngine* engine, const std::vector<FilterInfo*>& filterInfos, unsigned allChannelCount);
|
||||
~FilterConfiguration();
|
||||
|
||||
void process(float* input, unsigned frameCount);
|
||||
void read(float* input, unsigned frameCount);
|
||||
void read(float** input, unsigned frameCount);
|
||||
void process(unsigned frameCount);
|
||||
unsigned doTransition(FilterConfiguration* nextConfig, unsigned frameCount, unsigned transitionCounter, unsigned transitionLength);
|
||||
void write(float* output, unsigned frameCount);
|
||||
void write(float** output, unsigned frameCount);
|
||||
float** getOutputSamples() {return allSamples;}
|
||||
bool isEmpty();
|
||||
|
||||
|
||||
+43
-14
@@ -118,13 +118,14 @@ void FilterEngine::setPreMix(bool preMix)
|
||||
this->preMix = preMix;
|
||||
}
|
||||
|
||||
void FilterEngine::setDeviceInfo(bool capture, bool postMixInstalled, const wstring& deviceName, const wstring& connectionName, const wstring& deviceGuid)
|
||||
void FilterEngine::setDeviceInfo(bool capture, bool postMixInstalled, const wstring& deviceName, const wstring& connectionName, const wstring& deviceGuid, const wstring& deviceString)
|
||||
{
|
||||
this->capture = capture;
|
||||
this->postMixInstalled = postMixInstalled;
|
||||
this->deviceName = deviceName;
|
||||
this->connectionName = connectionName;
|
||||
this->deviceGuid = deviceGuid;
|
||||
this->deviceString = deviceString;
|
||||
}
|
||||
|
||||
void FilterEngine::initialize(float sampleRate, unsigned inputChannelCount, unsigned realChannelCount, unsigned outputChannelCount, unsigned channelMask, unsigned maxFrameCount, const wstring& customPath)
|
||||
@@ -268,7 +269,7 @@ void FilterEngine::loadConfigFile(const wstring& path)
|
||||
DWORD error = GetLastError();
|
||||
if (error != ERROR_SHARING_VIOLATION)
|
||||
{
|
||||
LogF(L"Error while reading configuration file: %s", StringHelper::getSystemErrorString(error).c_str());
|
||||
LogF(L"Error while reading configuration file %s: %s", path.c_str(), StringHelper::getSystemErrorString(error).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -377,27 +378,55 @@ void FilterEngine::process(float* output, float* input, unsigned frameCount)
|
||||
}
|
||||
}
|
||||
|
||||
currentConfig->process(input, frameCount);
|
||||
currentConfig->read(input, frameCount);
|
||||
currentConfig->process(frameCount);
|
||||
|
||||
if (nextConfig != NULL)
|
||||
{
|
||||
nextConfig->process(input, frameCount);
|
||||
float** currentSamples = currentConfig->getOutputSamples();
|
||||
float** nextSamples = nextConfig->getOutputSamples();
|
||||
nextConfig->read(input, frameCount);
|
||||
nextConfig->process(frameCount);
|
||||
transitionCounter = currentConfig->doTransition(nextConfig, frameCount, transitionCounter, transitionLength);
|
||||
}
|
||||
|
||||
for (unsigned f = 0; f < frameCount; f++)
|
||||
currentConfig->write(output, frameCount);
|
||||
|
||||
if (nextConfig != NULL && transitionCounter >= transitionLength)
|
||||
{
|
||||
previousConfig = currentConfig;
|
||||
currentConfig = nextConfig;
|
||||
nextConfig = NULL;
|
||||
transitionCounter = 0;
|
||||
ReleaseSemaphore(loadSemaphore, 1, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void FilterEngine::process(float** output, float** input, unsigned frameCount)
|
||||
{
|
||||
if (currentConfig->isEmpty() && nextConfig == NULL)
|
||||
{
|
||||
// avoid double copying cost if no processing will happen anyway
|
||||
if (realChannelCount == outputChannelCount)
|
||||
{
|
||||
float factor = 0.5f * (1.0f - cos(transitionCounter * (float)M_PI / transitionLength));
|
||||
if (transitionCounter >= transitionLength)
|
||||
factor = 1.0f;
|
||||
if (input != output)
|
||||
{
|
||||
for (unsigned c = 0; c < realChannelCount; c++)
|
||||
memcpy(output[c], input[c], frameCount * sizeof(float));
|
||||
}
|
||||
|
||||
for (unsigned c = 0; c < outputChannelCount; c++)
|
||||
currentSamples[c][f] = currentSamples[c][f] * (1 - factor) + nextSamples[c][f] * factor;
|
||||
|
||||
transitionCounter++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
currentConfig->read(input, frameCount);
|
||||
currentConfig->process(frameCount);
|
||||
|
||||
if (nextConfig != NULL)
|
||||
{
|
||||
nextConfig->read(input, frameCount);
|
||||
nextConfig->process(frameCount);
|
||||
transitionCounter = currentConfig->doTransition(nextConfig, frameCount, transitionCounter, transitionLength);
|
||||
}
|
||||
|
||||
currentConfig->write(output, frameCount);
|
||||
|
||||
if (nextConfig != NULL && transitionCounter >= transitionLength)
|
||||
|
||||
+4
-1
@@ -39,12 +39,13 @@ public:
|
||||
~FilterEngine();
|
||||
|
||||
void setPreMix(bool preMix);
|
||||
void setDeviceInfo(bool capture, bool postMixInstalled, const std::wstring& deviceName, const std::wstring& connectionName, const std::wstring& deviceGuid);
|
||||
void setDeviceInfo(bool capture, bool postMixInstalled, const std::wstring& deviceName, const std::wstring& connectionName, const std::wstring& deviceGuid, const std::wstring& deviceString);
|
||||
void initialize(float sampleRate, unsigned inputChannelCount, unsigned realChannelCount, unsigned outputChannelCount, unsigned channelMask, unsigned maxFrameCount, const std::wstring& customPath = L"");
|
||||
void loadConfig(const std::wstring& customPath = L"");
|
||||
void loadConfigFile(const std::wstring& path);
|
||||
void watchRegistryKey(const std::wstring& key);
|
||||
void process(float* output, float* input, unsigned frameCount);
|
||||
void process(float** output, float** input, unsigned frameCount);
|
||||
|
||||
bool isPreMix() const {return preMix;}
|
||||
bool isCapture() const {return capture;}
|
||||
@@ -52,6 +53,7 @@ public:
|
||||
std::wstring getDeviceName() const {return deviceName;}
|
||||
std::wstring getConnectionName() const {return connectionName;}
|
||||
std::wstring getDeviceGuid() const {return deviceGuid;}
|
||||
std::wstring getDeviceString() const {return deviceString;}
|
||||
unsigned getInputChannelCount() const {return inputChannelCount;}
|
||||
unsigned getRealChannelCount() const {return realChannelCount;}
|
||||
unsigned getOutputChannelCount() const {return outputChannelCount;}
|
||||
@@ -73,6 +75,7 @@ private:
|
||||
std::wstring deviceName;
|
||||
std::wstring connectionName;
|
||||
std::wstring deviceGuid;
|
||||
std::wstring deviceString;
|
||||
std::wstring configPath;
|
||||
float sampleRate;
|
||||
// number of input channels that originally existed before child APO processing
|
||||
|
||||
@@ -115,10 +115,12 @@ Section "Install" SecInstall
|
||||
!insertmacro RenameAndDelete "$INSTDIR\msvcr100.dll"
|
||||
!insertmacro RenameAndDelete "$INSTDIR\msvcp120.dll"
|
||||
!insertmacro RenameAndDelete "$INSTDIR\msvcr120.dll"
|
||||
!insertmacro RenameAndDelete "$INSTDIR\VoicemeeterClient.exe"
|
||||
|
||||
File "${BINPATH}\EqualizerAPO.dll"
|
||||
File "${BINPATH}\Configurator.exe"
|
||||
File "${BINPATH}\Benchmark.exe"
|
||||
File "${BINPATH}\VoicemeeterClient.exe"
|
||||
|
||||
File "${BINPATH_EDITOR}\Editor.exe"
|
||||
|
||||
@@ -227,6 +229,7 @@ Section "-un.Uninstall"
|
||||
|
||||
Delete "$INSTDIR\Editor.exe"
|
||||
|
||||
Delete "$INSTDIR\VoicemeeterClient.exe"
|
||||
Delete "$INSTDIR\Benchmark.exe"
|
||||
Delete "$INSTDIR\Configurator.exe"
|
||||
Delete /REBOOTOK "$INSTDIR\EqualizerAPO.dll"
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
# The result should be equivalent to the command
|
||||
# Filter: ON LP Fc 3000 Hz
|
||||
|
||||
Do: `freq = 3000`
|
||||
Do: `Q = 1/sqrt(2)`
|
||||
Do: `omega = 2 * pi * freq / sampleRate`
|
||||
Do: `sn = sin(omega)`
|
||||
Do: `cs = cos(omega)`
|
||||
Do: `alpha = sin(omega) / (2 * Q)`
|
||||
Do: `a0 = (1 - cs) / 2`
|
||||
Do: `a1 = 1 - cs`
|
||||
Do: `a2 = (1 - cs) / 2`
|
||||
Do: `b0 = 1 + alpha`
|
||||
Do: `b1 = -2 * cs`
|
||||
Do: `b2 = 1 - alpha`
|
||||
Eval: freq = 3000
|
||||
Eval: Q = 1/sqrt(2)
|
||||
Eval: omega = 2 * pi * freq / sampleRate
|
||||
Eval: sn = sin(omega)
|
||||
Eval: cs = cos(omega)
|
||||
Eval: alpha = sin(omega) / (2 * Q)
|
||||
Eval: a0 = (1 - cs) / 2
|
||||
Eval: a1 = 1 - cs
|
||||
Eval: a2 = (1 - cs) / 2
|
||||
Eval: b0 = 1 + alpha
|
||||
Eval: b1 = -2 * cs
|
||||
Eval: b2 = 1 - alpha
|
||||
|
||||
Filter: ON IIR Order 2 Coefficients `a0` `a1` `a2` `b0` `b1` `b2`
|
||||
Filter: ON IIR Order 2 Coefficients `a0` `a1` `a2` `b0` `b1` `b2`
|
||||
@@ -0,0 +1,501 @@
|
||||
/*
|
||||
This file is part of EqualizerAPO, a system-wide equalizer.
|
||||
Copyright (C) 2017 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 "stdafx.h"
|
||||
#include <ShlObj.h>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <KsMedia.h>
|
||||
#include <shellapi.h>
|
||||
#include <TlHelp32.h>
|
||||
#include <Winternl.h>
|
||||
#include "helpers/RegistryHelper.h"
|
||||
#include "VoicemeeterAPOInfo.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define voicemeeterKeyPath L"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VB:Voicemeeter {17359A74-1236-5467}"
|
||||
#define voicemeeterWowKeyPath L"HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VB:Voicemeeter {17359A74-1236-5467}"
|
||||
#define uninstallStringValueName L"UninstallString"
|
||||
static const wchar_t* startupFilename = L"Equalizer APO Voicemeeter Client.lnk";
|
||||
static const wchar_t* clientFilename = L"VoicemeeterClient.exe";
|
||||
static const wchar_t* voicemeeterClientKeyPath = USER_REGPATH L"\\Voicemeeter Client";
|
||||
static const wchar_t* sampleRateValueName = L"sampleRate";
|
||||
|
||||
typedef NTSTATUS (NTAPI * pfnNtQueryInformationProcess)(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PROCESSINFOCLASS ProcessInformationClass,
|
||||
OUT PVOID ProcessInformation,
|
||||
IN ULONG ProcessInformationLength,
|
||||
OUT PULONG ReturnLength OPTIONAL
|
||||
);
|
||||
|
||||
void VoicemeeterAPOInfo::prependInfos(vector<shared_ptr<AbstractAPOInfo> >& list)
|
||||
{
|
||||
wstring voicemeeterDirectory;
|
||||
if (RegistryHelper::keyExists(voicemeeterKeyPath))
|
||||
voicemeeterDirectory = RegistryHelper::readValue(voicemeeterKeyPath, uninstallStringValueName);
|
||||
else if (RegistryHelper::keyExists(voicemeeterWowKeyPath))
|
||||
voicemeeterDirectory = RegistryHelper::readValue(voicemeeterWowKeyPath, uninstallStringValueName);
|
||||
|
||||
if (voicemeeterDirectory.length() > 0)
|
||||
{
|
||||
size_t index = voicemeeterDirectory.find_last_of(L'\\');
|
||||
|
||||
wstring setupFilename = voicemeeterDirectory.substr(index + 1);
|
||||
bool banana = (setupFilename == L"VoicemeeterProSetup.exe");
|
||||
|
||||
unsigned outputCount;
|
||||
if (banana)
|
||||
outputCount = 3;
|
||||
else
|
||||
outputCount = 1;
|
||||
|
||||
bool defaultDevice = false;
|
||||
list.erase(remove_if(list.begin(), list.end(), [&defaultDevice](shared_ptr<AbstractAPOInfo>& info) {
|
||||
if (info->getDeviceName().find(L"VB-Audio VoiceMeeter") != wstring::npos)
|
||||
{
|
||||
if (info->isDefaultDevice())
|
||||
defaultDevice = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}), list.end());
|
||||
|
||||
bool anyInstalled = false;
|
||||
for (unsigned i = 0; i < outputCount; i++)
|
||||
{
|
||||
wstringstream sstream;
|
||||
sstream << "Output A" << (i + 1);
|
||||
shared_ptr<AbstractAPOInfo> info = *list.insert(list.begin() + i, make_shared<VoicemeeterAPOInfo>(sstream.str(), true));
|
||||
if (info->isInstalled())
|
||||
anyInstalled = true;
|
||||
}
|
||||
|
||||
if (defaultDevice)
|
||||
{
|
||||
for (unsigned i = 0; i < outputCount; i++)
|
||||
{
|
||||
shared_ptr<VoicemeeterAPOInfo>& info = (shared_ptr<VoicemeeterAPOInfo>&)list[i];
|
||||
if (!anyInstalled || info->isInstalled())
|
||||
{
|
||||
info->defaultDevice = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Voicemeeter was uninstalled but Voicemeeter Client might still be installed
|
||||
wstring startupFilePath = getStartupPath();
|
||||
wstring argString = getLinkArgs(startupFilePath);
|
||||
vector<wstring> args = splitArgs(argString);
|
||||
|
||||
int i = 0;
|
||||
for (wstring arg : args)
|
||||
{
|
||||
shared_ptr<AbstractAPOInfo> info = *list.insert(list.begin() + i, make_shared<VoicemeeterAPOInfo>(arg, false));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VoicemeeterAPOInfo::VoicemeeterAPOInfo(const wstring& connectionName, bool voicemeeterInstalled)
|
||||
: connectionName(connectionName), voicemeeterInstalled(voicemeeterInstalled)
|
||||
{
|
||||
wstring startupFilePath = getStartupPath();
|
||||
wstring path;
|
||||
wstring argString = getLinkArgs(startupFilePath, &path);
|
||||
vector<wstring> args = splitArgs(argString);
|
||||
installed = find(args.begin(), args.end(), connectionName) != args.end();
|
||||
|
||||
sampleRate = 48000;
|
||||
try
|
||||
{
|
||||
if (RegistryHelper::keyExists(voicemeeterClientKeyPath) && RegistryHelper::valueExists(voicemeeterClientKeyPath, sampleRateValueName))
|
||||
sampleRate = (unsigned)RegistryHelper::readDWORDValue(voicemeeterClientKeyPath, sampleRateValueName);
|
||||
}
|
||||
catch (RegistryException e)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
wstring clientPath = getClientPath();
|
||||
changes = (path != clientPath);
|
||||
}
|
||||
|
||||
wstring VoicemeeterAPOInfo::getConnectionName() const
|
||||
{
|
||||
return connectionName;
|
||||
}
|
||||
|
||||
wstring VoicemeeterAPOInfo::getDeviceName() const
|
||||
{
|
||||
return L"Voicemeeter";
|
||||
}
|
||||
|
||||
wstring VoicemeeterAPOInfo::getDeviceGuid() const
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
||||
wstring VoicemeeterAPOInfo::getDeviceString() const
|
||||
{
|
||||
return getConnectionName() + L" " + getDeviceName();
|
||||
}
|
||||
|
||||
unsigned VoicemeeterAPOInfo::getChannelCount() const
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
unsigned VoicemeeterAPOInfo::getSampleRate() const
|
||||
{
|
||||
return sampleRate;
|
||||
}
|
||||
|
||||
unsigned long VoicemeeterAPOInfo::getChannelMask() const
|
||||
{
|
||||
return KSAUDIO_SPEAKER_7POINT1_SURROUND;
|
||||
}
|
||||
|
||||
bool VoicemeeterAPOInfo::isInput() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VoicemeeterAPOInfo::isInstalled() const
|
||||
{
|
||||
return installed;
|
||||
}
|
||||
|
||||
bool VoicemeeterAPOInfo::canBeUpgraded() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VoicemeeterAPOInfo::hasChanges() const
|
||||
{
|
||||
return changes;
|
||||
}
|
||||
|
||||
bool VoicemeeterAPOInfo::isExperimental() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VoicemeeterAPOInfo::isEnhancementsDisabled() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VoicemeeterAPOInfo::isDefaultDevice() const
|
||||
{
|
||||
return defaultDevice;
|
||||
}
|
||||
|
||||
bool VoicemeeterAPOInfo::isVoicemeeterInstalled() const
|
||||
{
|
||||
return voicemeeterInstalled;
|
||||
}
|
||||
|
||||
void VoicemeeterAPOInfo::install()
|
||||
{
|
||||
wstring startupFilePath = getStartupPath();
|
||||
wstring argString = getLinkArgs(startupFilePath);
|
||||
vector<wstring> args = splitArgs(argString);
|
||||
vector<wstring>::iterator it = find(args.begin(), args.end(), connectionName);
|
||||
if (it == args.end())
|
||||
args.push_back(connectionName);
|
||||
sort(args.begin(), args.end());
|
||||
argString = joinArgs(args);
|
||||
|
||||
wstring clientPath = getClientPath();
|
||||
|
||||
createLink(startupFilePath, clientPath, argString);
|
||||
}
|
||||
|
||||
void VoicemeeterAPOInfo::uninstall()
|
||||
{
|
||||
wstring startupFilePath = getStartupPath();
|
||||
wstring argString = getLinkArgs(startupFilePath);
|
||||
vector<wstring> args = splitArgs(argString);
|
||||
vector<wstring>::iterator it = find(args.begin(), args.end(), connectionName);
|
||||
if (it != args.end())
|
||||
args.erase(it);
|
||||
if (args.size() > 0)
|
||||
{
|
||||
sort(args.begin(), args.end());
|
||||
argString = joinArgs(args);
|
||||
|
||||
wchar_t filename[MAX_PATH];
|
||||
GetModuleFileNameW(NULL, filename, ARRAYSIZE(filename));
|
||||
PathRemoveFileSpecW(filename);
|
||||
wstring clientPath = filename;
|
||||
clientPath = clientPath + L"\\" + clientFilename;
|
||||
|
||||
createLink(startupFilePath, clientPath, argString);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteFileW(startupFilePath.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void VoicemeeterAPOInfo::reinstall()
|
||||
{
|
||||
uninstall();
|
||||
install();
|
||||
}
|
||||
|
||||
wstring VoicemeeterAPOInfo::getStartupPath()
|
||||
{
|
||||
PWSTR startupPath;
|
||||
SHGetKnownFolderPath(FOLDERID_Startup, KF_FLAG_DONT_UNEXPAND, NULL, &startupPath);
|
||||
wstring result(startupPath);
|
||||
|
||||
CoTaskMemFree(startupPath);
|
||||
|
||||
return result + L"\\" + startupFilename;
|
||||
}
|
||||
|
||||
wstring VoicemeeterAPOInfo::getClientPath()
|
||||
{
|
||||
wchar_t filename[MAX_PATH];
|
||||
GetModuleFileNameW(NULL, filename, ARRAYSIZE(filename));
|
||||
PathRemoveFileSpecW(filename);
|
||||
wstring clientPath = filename;
|
||||
clientPath = clientPath + L"\\" + clientFilename;
|
||||
|
||||
return clientPath;
|
||||
}
|
||||
|
||||
void VoicemeeterAPOInfo::createLink(const wstring& lnkPath, const wstring& path, const wstring& args)
|
||||
{
|
||||
IShellLink* shellLink;
|
||||
HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&shellLink);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
shellLink->SetPath(path.c_str());
|
||||
shellLink->SetArguments(args.c_str());
|
||||
IPersistFile* persistFile;
|
||||
hr = shellLink->QueryInterface(IID_IPersistFile, (LPVOID*)&persistFile);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = persistFile->Save(lnkPath.c_str(), TRUE);
|
||||
persistFile->Release();
|
||||
}
|
||||
|
||||
shellLink->Release();
|
||||
}
|
||||
}
|
||||
|
||||
wstring VoicemeeterAPOInfo::getLinkArgs(const wstring& lnkPath, wstring* path)
|
||||
{
|
||||
wstring result;
|
||||
|
||||
IShellLink* shellLink;
|
||||
HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&shellLink);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IPersistFile* persistFile;
|
||||
hr = shellLink->QueryInterface(IID_IPersistFile, (LPVOID*)&persistFile);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = persistFile->Load(lnkPath.c_str(), STGM_READ);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
wchar_t buf[MAX_PATH];
|
||||
hr = shellLink->GetArguments(buf, ARRAYSIZE(buf));
|
||||
if (SUCCEEDED(hr))
|
||||
result = buf;
|
||||
|
||||
if (path != NULL)
|
||||
{
|
||||
hr = shellLink->GetPath(buf, ARRAYSIZE(buf), NULL, 0);
|
||||
if (SUCCEEDED(hr))
|
||||
*path = buf;
|
||||
}
|
||||
}
|
||||
persistFile->Release();
|
||||
}
|
||||
|
||||
shellLink->Release();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<wstring> VoicemeeterAPOInfo::splitArgs(const wstring& argString)
|
||||
{
|
||||
vector<wstring> result;
|
||||
|
||||
if (argString.length() > 0)
|
||||
{
|
||||
int argc;
|
||||
wchar_t** argv = CommandLineToArgvW(argString.c_str(), &argc);
|
||||
for (int i = 0; i < argc; i++)
|
||||
result.push_back(argv[i]);
|
||||
LocalFree(argv);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
wstring VoicemeeterAPOInfo::joinArgs(const vector<wstring>& args)
|
||||
{
|
||||
wstring result;
|
||||
for (const wstring& arg : args)
|
||||
{
|
||||
if (result.length() > 0)
|
||||
result += L" ";
|
||||
|
||||
if (arg.find(' ') != wstring::npos)
|
||||
result += L"\"" + arg + L"\"";
|
||||
else
|
||||
result += arg;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void VoicemeeterAPOInfo::ensureVoicemeeterClientRunning()
|
||||
{
|
||||
wstring startupFilePath = getStartupPath();
|
||||
wstring argString = getLinkArgs(startupFilePath);
|
||||
vector<wstring> args = splitArgs(argString);
|
||||
wstring clientPath = getClientPath();
|
||||
|
||||
HANDLE tokenHandle;
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenHandle))
|
||||
throw RegistryException(L"Error in OpenProcessToken while taking ownership");
|
||||
|
||||
LUID luid;
|
||||
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
|
||||
throw RegistryException(L"Error in LookupPrivilegeValue while taking ownership");
|
||||
|
||||
TOKEN_PRIVILEGES tp;
|
||||
tp.PrivilegeCount = 1;
|
||||
tp.Privileges[0].Luid = luid;
|
||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
|
||||
if (!AdjustTokenPrivileges(tokenHandle, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
|
||||
throw RegistryException(L"Error in AdjustTokenPrivileges while taking ownership");
|
||||
|
||||
HMODULE module = LoadLibraryW(L"ntdll.dll");
|
||||
if (module == NULL)
|
||||
throw exception("Could not load ntdll.dll");
|
||||
SCOPE_EXIT {FreeLibrary(module);};
|
||||
|
||||
pfnNtQueryInformationProcess NtQueryInformationProcess = (pfnNtQueryInformationProcess)GetProcAddress(module, "NtQueryInformationProcess");
|
||||
if (NtQueryInformationProcess == NULL)
|
||||
throw exception("Function NtQueryInformationProcess not found in ntdll.dll");
|
||||
|
||||
HANDLE snapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (snapshotHandle == INVALID_HANDLE_VALUE)
|
||||
throw exception("Could not take a snapshot of all processes");
|
||||
SCOPE_EXIT {CloseHandle(snapshotHandle);};
|
||||
|
||||
bool matchingProcessExists = false;
|
||||
|
||||
PROCESSENTRY32W entry;
|
||||
entry.dwSize = sizeof(PROCESSENTRY32W);
|
||||
bool loop = Process32FirstW(snapshotHandle, &entry) != 0;
|
||||
while (loop)
|
||||
{
|
||||
if (wcscmp(entry.szExeFile, clientFilename) == 0)
|
||||
{
|
||||
HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, FALSE, entry.th32ProcessID);
|
||||
if (processHandle == INVALID_HANDLE_VALUE)
|
||||
throw exception("Could not open process");
|
||||
SCOPE_EXIT {CloseHandle(processHandle);};
|
||||
|
||||
PROCESS_BASIC_INFORMATION basicInformation;
|
||||
NTSTATUS status = NtQueryInformationProcess(processHandle, ProcessBasicInformation, &basicInformation, sizeof(basicInformation), NULL);
|
||||
if (status < 0)
|
||||
throw exception("Could not query process information");
|
||||
|
||||
_PEB peb;
|
||||
if (!ReadProcessMemory(processHandle, basicInformation.PebBaseAddress, &peb, sizeof(peb), NULL))
|
||||
throw exception("Could not read peb from process memory");
|
||||
|
||||
RTL_USER_PROCESS_PARAMETERS processParams;
|
||||
if (!ReadProcessMemory(processHandle, peb.ProcessParameters, &processParams, sizeof(processParams), NULL))
|
||||
throw exception("Could not read process parameters from process memory");
|
||||
|
||||
wchar_t* cmdLineBuf = new wchar_t[processParams.CommandLine.Length / sizeof(wchar_t)];
|
||||
SCOPE_EXIT {delete cmdLineBuf;};
|
||||
if (!ReadProcessMemory(processHandle, processParams.CommandLine.Buffer, cmdLineBuf, processParams.CommandLine.Length, NULL))
|
||||
throw exception("Could not read command line from process memory");
|
||||
wstring cmdLine(cmdLineBuf, processParams.CommandLine.Length / sizeof(wchar_t));
|
||||
|
||||
vector<wstring> processArgs = splitArgs(cmdLine);
|
||||
wstring path = processArgs.front();
|
||||
processArgs.erase(processArgs.begin());
|
||||
|
||||
if (path != clientPath || processArgs != args)
|
||||
closeProcess(entry.th32ProcessID);
|
||||
else
|
||||
matchingProcessExists = true;
|
||||
}
|
||||
|
||||
loop = Process32NextW(snapshotHandle, &entry) != 0;
|
||||
}
|
||||
|
||||
if (!matchingProcessExists && !args.empty())
|
||||
{
|
||||
ShellExecuteW(NULL, NULL, clientPath.c_str(), argString.c_str(), NULL, SW_SHOWDEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
void VoicemeeterAPOInfo::saveVoicemeeterSampleRate(unsigned sampleRate)
|
||||
{
|
||||
try
|
||||
{
|
||||
RegistryHelper::createKey(voicemeeterClientKeyPath);
|
||||
RegistryHelper::writeDWORDValue(voicemeeterClientKeyPath, sampleRateValueName, sampleRate);
|
||||
}
|
||||
catch (RegistryException e)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
void VoicemeeterAPOInfo::closeProcess(unsigned long processId)
|
||||
{
|
||||
HANDLE snapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
||||
if (snapshotHandle == INVALID_HANDLE_VALUE)
|
||||
throw exception("Could not take a snapshot of all processes");
|
||||
SCOPE_EXIT {CloseHandle(snapshotHandle);};
|
||||
|
||||
THREADENTRY32 entry;
|
||||
entry.dwSize = sizeof(THREADENTRY32);
|
||||
bool loop = Thread32First(snapshotHandle, &entry) != 0;
|
||||
while (loop)
|
||||
{
|
||||
if (entry.th32OwnerProcessID == processId)
|
||||
// will just fail for threads not having a message queue
|
||||
PostThreadMessageW(entry.th32ThreadID, WM_QUIT, 0, 0);
|
||||
|
||||
loop = Thread32Next(snapshotHandle, &entry) != 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
This file is part of EqualizerAPO, a system-wide equalizer.
|
||||
Copyright (C) 2017 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 <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "AbstractAPOInfo.h"
|
||||
|
||||
class VoicemeeterAPOInfo : public AbstractAPOInfo
|
||||
{
|
||||
public:
|
||||
static void prependInfos(std::vector<std::shared_ptr<AbstractAPOInfo> >& list);
|
||||
|
||||
VoicemeeterAPOInfo(const std::wstring& connectionName, bool voicemeeterInstalled);
|
||||
|
||||
std::wstring getConnectionName() const override;
|
||||
std::wstring getDeviceName() const override;
|
||||
std::wstring getDeviceGuid() const override;
|
||||
std::wstring getDeviceString() const override;
|
||||
unsigned getChannelCount() const override;
|
||||
unsigned getSampleRate() const override;
|
||||
unsigned long getChannelMask() const override;
|
||||
bool isInput() const override;
|
||||
bool isInstalled() const override;
|
||||
bool canBeUpgraded() const override;
|
||||
bool hasChanges() const override;
|
||||
bool isExperimental() const override;
|
||||
bool isEnhancementsDisabled() const override;
|
||||
bool isDefaultDevice() const override;
|
||||
bool isVoicemeeterInstalled() const;
|
||||
void install() override;
|
||||
void uninstall() override;
|
||||
void reinstall() override;
|
||||
static void ensureVoicemeeterClientRunning();
|
||||
static void saveVoicemeeterSampleRate(unsigned sampleRate);
|
||||
|
||||
private:
|
||||
static std::wstring getStartupPath();
|
||||
static std::wstring getClientPath();
|
||||
static void createLink(const std::wstring& lnkPath, const std::wstring& path, const std::wstring& args);
|
||||
static std::wstring getLinkArgs(const std::wstring& lnkPath, std::wstring* path = NULL);
|
||||
static std::vector<std::wstring> splitArgs(const std::wstring& argString);
|
||||
static std::wstring joinArgs(const std::vector<std::wstring>& args);
|
||||
static void closeProcess(unsigned long processId);
|
||||
|
||||
std::wstring connectionName;
|
||||
unsigned sampleRate;
|
||||
bool installed;
|
||||
bool defaultDevice = false;
|
||||
bool voicemeeterInstalled;
|
||||
bool changes = false;
|
||||
};
|
||||
@@ -0,0 +1,266 @@
|
||||
#include "stdafx.h"
|
||||
#include <string>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#include "helpers/RegistryHelper.h"
|
||||
#include "VoicemeeterClient.h"
|
||||
#include "VoicemeeterAPOInfo.h"
|
||||
|
||||
#define voicemeeterKeyPath L"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VB:Voicemeeter {17359A74-1236-5467}"
|
||||
#define voicemeeterWowKeyPath L"HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VB:Voicemeeter {17359A74-1236-5467}"
|
||||
#define uninstallStringValueName L"UninstallString"
|
||||
|
||||
using namespace std;
|
||||
|
||||
long __stdcall callback(void* lpUser, long nCommand, void* lpData, long nnn);
|
||||
|
||||
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
|
||||
_In_opt_ HINSTANCE hPrevInstance,
|
||||
_In_ LPTSTR lpCmdLine,
|
||||
_In_ int nCmdShow)
|
||||
{
|
||||
vector<wstring> outputs;
|
||||
if (lpCmdLine[0] != 0)
|
||||
{
|
||||
int argc;
|
||||
wchar_t** argv = CommandLineToArgvW(lpCmdLine, &argc);
|
||||
for (int i = 0; i < argc; i++)
|
||||
outputs.push_back(argv[i]);
|
||||
LocalFree(argv);
|
||||
}
|
||||
|
||||
VoicemeeterClient* client = new VoicemeeterClient(outputs);
|
||||
|
||||
MSG msg;
|
||||
msg.wParam = 0;
|
||||
|
||||
bool loop = client->restart;
|
||||
while (loop)
|
||||
{
|
||||
client->start();
|
||||
client->restart = false;
|
||||
|
||||
while (GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
loop = client->restart;
|
||||
|
||||
client->stop();
|
||||
}
|
||||
delete client;
|
||||
|
||||
return (int)msg.wParam;
|
||||
}
|
||||
|
||||
VoicemeeterClient::VoicemeeterClient(const vector<wstring>& outputs)
|
||||
: outputs(outputs)
|
||||
{
|
||||
mainThreadId = GetCurrentThreadId();
|
||||
|
||||
wstring voicemeeterDirectory;
|
||||
if (RegistryHelper::keyExists(voicemeeterKeyPath))
|
||||
voicemeeterDirectory = RegistryHelper::readValue(voicemeeterKeyPath, uninstallStringValueName);
|
||||
else if (RegistryHelper::keyExists(voicemeeterWowKeyPath))
|
||||
voicemeeterDirectory = RegistryHelper::readValue(voicemeeterWowKeyPath, uninstallStringValueName);
|
||||
|
||||
size_t index = voicemeeterDirectory.find_last_of(L'\\');
|
||||
HMODULE voicemeeterModule = NULL;
|
||||
|
||||
if (index != wstring::npos)
|
||||
{
|
||||
wstring setupFilename = voicemeeterDirectory.substr(index + 1);
|
||||
banana = (setupFilename == L"VoicemeeterProSetup.exe");
|
||||
|
||||
voicemeeterDirectory = voicemeeterDirectory.substr(0, index);
|
||||
|
||||
#ifdef _WIN64
|
||||
voicemeeterModule = LoadLibraryW((voicemeeterDirectory + L"\\VoicemeeterRemote64.dll").c_str());
|
||||
#else
|
||||
voicemeeterModule = LoadLibraryW((voicemeeterDirectory + L"\\VoicemeeterRemote.dll").c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
memset(&vmr, 0, sizeof(T_VBVMR_INTERFACE));
|
||||
#define LOAD_PROC(proc) vmr.proc = (T_ ## proc)GetProcAddress(voicemeeterModule, # proc)
|
||||
if (voicemeeterModule != NULL)
|
||||
{
|
||||
LOAD_PROC(VBVMR_Login);
|
||||
LOAD_PROC(VBVMR_Logout);
|
||||
LOAD_PROC(VBVMR_AudioCallbackRegister);
|
||||
LOAD_PROC(VBVMR_AudioCallbackStart);
|
||||
LOAD_PROC(VBVMR_AudioCallbackStop);
|
||||
LOAD_PROC(VBVMR_AudioCallbackUnregister);
|
||||
LOAD_PROC(VBVMR_GetVoicemeeterType);
|
||||
|
||||
restart = true;
|
||||
}
|
||||
}
|
||||
|
||||
VoicemeeterClient::~VoicemeeterClient()
|
||||
{
|
||||
if (loggedIn)
|
||||
{
|
||||
vmr.VBVMR_Logout();
|
||||
loggedIn = false;
|
||||
}
|
||||
}
|
||||
|
||||
void VoicemeeterClient::start()
|
||||
{
|
||||
if (!loggedIn)
|
||||
loggedIn = (vmr.VBVMR_Login() == 0);
|
||||
|
||||
if (loggedIn)
|
||||
{
|
||||
long type;
|
||||
if (vmr.VBVMR_GetVoicemeeterType(&type) == 0)
|
||||
banana = (type == 2);
|
||||
}
|
||||
|
||||
unsigned outputCount;
|
||||
if (banana)
|
||||
outputCount = 3;
|
||||
else
|
||||
outputCount = 1;
|
||||
|
||||
for (unsigned i = 0; i < outputCount; i++)
|
||||
{
|
||||
wstringstream sstream;
|
||||
sstream << "Output A" << (i + 1);
|
||||
wstring output = sstream.str();
|
||||
if (find(outputs.begin(), outputs.end(), output) != outputs.end())
|
||||
{
|
||||
FilterEngine* engine = new FilterEngine();
|
||||
engine->setDeviceInfo(false, true, L"Voicemeeter", output, L"", L"Voicemeeter " + output);
|
||||
engines.push_back(engine);
|
||||
}
|
||||
else
|
||||
{
|
||||
engines.push_back(NULL);
|
||||
}
|
||||
|
||||
idleSampleCounts.push_back(0);
|
||||
}
|
||||
|
||||
if (vmr.VBVMR_AudioCallbackRegister(VBVMR_AUDIOCALLBACK_OUT, callback, this, "Equalizer APO") != 0)
|
||||
{
|
||||
PostThreadMessage(mainThreadId, WM_QUIT, 0, 0);
|
||||
return;
|
||||
}
|
||||
vmr.VBVMR_AudioCallbackStart();
|
||||
}
|
||||
|
||||
void VoicemeeterClient::stop()
|
||||
{
|
||||
vmr.VBVMR_AudioCallbackStop();
|
||||
vmr.VBVMR_AudioCallbackUnregister();
|
||||
|
||||
idleSampleCounts.clear();
|
||||
for (FilterEngine* engine : engines)
|
||||
if (engine != NULL)
|
||||
delete engine;
|
||||
engines.clear();
|
||||
}
|
||||
|
||||
void VoicemeeterClient::handle(long nCommand, void* lpData, long nnn)
|
||||
{
|
||||
switch (nCommand)
|
||||
{
|
||||
case VBVMR_CBCOMMAND_STARTING:
|
||||
{
|
||||
VBVMR_LPT_AUDIOINFO audioInfo = (VBVMR_LPT_AUDIOINFO)lpData;
|
||||
for (FilterEngine* engine : engines)
|
||||
if (engine != NULL)
|
||||
engine->initialize((float)audioInfo->samplerate, 8, 8, 8, 0, audioInfo->nbSamplePerFrame);
|
||||
VoicemeeterAPOInfo::saveVoicemeeterSampleRate((unsigned)audioInfo->samplerate);
|
||||
}
|
||||
break;
|
||||
case VBVMR_CBCOMMAND_ENDING:
|
||||
{
|
||||
restart = true;
|
||||
PostThreadMessage(mainThreadId, WM_QUIT, 0, 0);
|
||||
}
|
||||
break;
|
||||
case VBVMR_CBCOMMAND_CHANGE:
|
||||
{
|
||||
VBVMR_LPT_AUDIOINFO audioInfo = (VBVMR_LPT_AUDIOINFO)lpData;
|
||||
for (FilterEngine* engine : engines)
|
||||
if (engine != NULL)
|
||||
engine->initialize((float)audioInfo->samplerate, 8, 8, 8, 0, audioInfo->nbSamplePerFrame);
|
||||
VoicemeeterAPOInfo::saveVoicemeeterSampleRate((unsigned)audioInfo->samplerate);
|
||||
}
|
||||
break;
|
||||
case VBVMR_CBCOMMAND_BUFFER_OUT:
|
||||
{
|
||||
VBVMR_LPT_AUDIOBUFFER audioBuffer = (VBVMR_LPT_AUDIOBUFFER)lpData;
|
||||
int nbi = audioBuffer->audiobuffer_nbi;
|
||||
int nbo = audioBuffer->audiobuffer_nbo;
|
||||
int n = min(nbi, nbo) / 8;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
FilterEngine* engine = NULL;
|
||||
if (i < engines.size())
|
||||
engine = engines[i];
|
||||
|
||||
bool idle = true;
|
||||
bool inputSilent = true;
|
||||
if (engine != NULL)
|
||||
{
|
||||
inputSilent = isBufferSilent(audioBuffer->audiobuffer_r + 8 * i, audioBuffer->audiobuffer_nbs);
|
||||
idle = inputSilent && idleSampleCounts[i] > 10 * engine->getSampleRate();
|
||||
}
|
||||
|
||||
// avoid processing when idle (Voicemeeter does still call this when no audio is played)
|
||||
if (!idle)
|
||||
{
|
||||
engine->process(audioBuffer->audiobuffer_w + 8 * i, audioBuffer->audiobuffer_r + 8 * i, audioBuffer->audiobuffer_nbs);
|
||||
|
||||
bool outputSilent = isBufferSilent(audioBuffer->audiobuffer_w + 8 * i, audioBuffer->audiobuffer_nbs);
|
||||
if (inputSilent && outputSilent)
|
||||
idleSampleCounts[i] += audioBuffer->audiobuffer_nbs;
|
||||
else
|
||||
idleSampleCounts[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < 8; j++)
|
||||
memcpy(audioBuffer->audiobuffer_w[8 * i + j], audioBuffer->audiobuffer_r[8 * i + j], audioBuffer->audiobuffer_nbs * sizeof(float));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool VoicemeeterClient::isBufferSilent(float** sampleData, long sampleCount)
|
||||
{
|
||||
bool silent = true;
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
float* buf = sampleData[j];
|
||||
for (int k = 0; k < sampleCount; k++)
|
||||
{
|
||||
if (buf[k] != 0.0f)
|
||||
{
|
||||
silent = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return silent;
|
||||
}
|
||||
|
||||
long __stdcall callback(void* lpUser, long nCommand, void* lpData, long nnn)
|
||||
{
|
||||
VoicemeeterClient* client = (VoicemeeterClient*)lpUser;
|
||||
client->handle(nCommand, lpData, nnn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "FilterEngine.h"
|
||||
#include "VoicemeeterRemote.h"
|
||||
|
||||
class VoicemeeterClient
|
||||
{
|
||||
public:
|
||||
VoicemeeterClient(const std::vector<std::wstring>& outputs);
|
||||
~VoicemeeterClient();
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
void handle(long nCommand, void* lpData, long nnn);
|
||||
bool restart = false;
|
||||
|
||||
private:
|
||||
bool isBufferSilent(float** sampleData, long sampleCount);
|
||||
|
||||
unsigned long mainThreadId;
|
||||
T_VBVMR_INTERFACE vmr;
|
||||
std::vector<FilterEngine*> engines;
|
||||
std::vector<int> idleSampleCounts;
|
||||
bool loggedIn = false;
|
||||
bool banana = false;
|
||||
std::vector<std::wstring> outputs;
|
||||
};
|
||||
Binary file not shown.
@@ -0,0 +1,249 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{10F1DD37-EA50-46C2-810D-D01A1A0D4D2F}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>VoicemeeterClient</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(SolutionDir);C:\Program Files\libsndfile\include;C:\Program Files\muparserx_v3_0_1\parser;C:\Program Files (x86)\fftw3;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\Program Files (x86)\libsndfile\lib;C:\Program Files\muparserx_v3_0_1\lib;C:\Program Files (x86)\fftw3;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(SolutionDir);C:\Program Files\libsndfile\include;C:\Program Files\muparserx_v3_0_1\parser;C:\Program Files\fftw3;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\Program Files\libsndfile\lib;C:\Program Files\muparserx_v3_0_1\lib64;C:\Program Files\fftw3;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(SolutionDir);C:\Program Files\libsndfile\include;C:\Program Files\muparserx_v3_0_1\parser;C:\Program Files (x86)\fftw3;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\Program Files (x86)\libsndfile\lib;C:\Program Files\muparserx_v3_0_1\lib;C:\Program Files (x86)\fftw3;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(SolutionDir);C:\Program Files\libsndfile\include;C:\Program Files\muparserx_v3_0_1\parser;C:\Program Files\fftw3;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\Program Files\libsndfile\lib;C:\Program Files\muparserx_v3_0_1\lib64;C:\Program Files\fftw3;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>muparserxd.lib;version.lib;Shlwapi.lib;authz.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>muparserxd.lib;version.lib;Shlwapi.lib;authz.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>muparserx.lib;version.lib;Shlwapi.lib;authz.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>muparserx.lib;version.lib;Shlwapi.lib;authz.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\..\..\Users\Jonas\Downloads\VoicemeeterRemoteAPI_Pack6\VoicemeeterRemote.h" />
|
||||
<ClInclude Include="..\AbstractAPOInfo.h" />
|
||||
<ClInclude Include="..\FilterConfiguration.h" />
|
||||
<ClInclude Include="..\FilterEngine.h" />
|
||||
<ClInclude Include="..\filters\BiQuad.h" />
|
||||
<ClInclude Include="..\filters\BiQuadFilter.h" />
|
||||
<ClInclude Include="..\filters\BiQuadFilterFactory.h" />
|
||||
<ClInclude Include="..\filters\ChannelFilter.h" />
|
||||
<ClInclude Include="..\filters\ChannelFilterFactory.h" />
|
||||
<ClInclude Include="..\filters\ConvolutionFilter.h" />
|
||||
<ClInclude Include="..\filters\ConvolutionFilterFactory.h" />
|
||||
<ClInclude Include="..\filters\CopyFilter.h" />
|
||||
<ClInclude Include="..\filters\CopyFilterFactory.h" />
|
||||
<ClInclude Include="..\filters\DelayFilter.h" />
|
||||
<ClInclude Include="..\filters\DelayFilterFactory.h" />
|
||||
<ClInclude Include="..\filters\DeviceFilterFactory.h" />
|
||||
<ClInclude Include="..\filters\ExpressionFilterFactory.h" />
|
||||
<ClInclude Include="..\filters\GraphicEQFilter.h" />
|
||||
<ClInclude Include="..\filters\GraphicEQFilterFactory.h" />
|
||||
<ClInclude Include="..\filters\IfFilterFactory.h" />
|
||||
<ClInclude Include="..\filters\IIRFilter.h" />
|
||||
<ClInclude Include="..\filters\IIRFilterFactory.h" />
|
||||
<ClInclude Include="..\filters\IncludeFilterFactory.h" />
|
||||
<ClInclude Include="..\filters\PreampFilter.h" />
|
||||
<ClInclude Include="..\filters\PreampFilterFactory.h" />
|
||||
<ClInclude Include="..\filters\StageFilterFactory.h" />
|
||||
<ClInclude Include="..\helpers\ChannelHelper.h" />
|
||||
<ClInclude Include="..\helpers\GainIterator.h" />
|
||||
<ClInclude Include="..\helpers\LogHelper.h" />
|
||||
<ClInclude Include="..\helpers\MemoryHelper.h" />
|
||||
<ClInclude Include="..\helpers\RegistryHelper.h" />
|
||||
<ClInclude Include="..\helpers\ScopeGuard.h" />
|
||||
<ClInclude Include="..\helpers\StringHelper.h" />
|
||||
<ClInclude Include="..\helpers\UncaughtExceptions.h" />
|
||||
<ClInclude Include="..\IFilter.h" />
|
||||
<ClInclude Include="..\IFilterFactory.h" />
|
||||
<ClInclude Include="..\libHybridConv-0.1.1\libHybridConv_eapo.h" />
|
||||
<ClInclude Include="..\parser\RegexFunctions.h" />
|
||||
<ClInclude Include="..\parser\RegistryFunctions.h" />
|
||||
<ClInclude Include="..\parser\StringOperators.h" />
|
||||
<ClInclude Include="..\stdafx.h" />
|
||||
<ClInclude Include="..\VoicemeeterAPOInfo.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="VoicemeeterClient.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\AbstractAPOInfo.cpp" />
|
||||
<ClCompile Include="..\FilterConfiguration.cpp" />
|
||||
<ClCompile Include="..\FilterEngine.cpp" />
|
||||
<ClCompile Include="..\filters\BiQuad.cpp" />
|
||||
<ClCompile Include="..\filters\BiQuadFilter.cpp" />
|
||||
<ClCompile Include="..\filters\BiQuadFilterFactory.cpp" />
|
||||
<ClCompile Include="..\filters\ChannelFilter.cpp" />
|
||||
<ClCompile Include="..\filters\ChannelFilterFactory.cpp" />
|
||||
<ClCompile Include="..\filters\ConvolutionFilter.cpp" />
|
||||
<ClCompile Include="..\filters\ConvolutionFilterFactory.cpp" />
|
||||
<ClCompile Include="..\filters\CopyFilter.cpp" />
|
||||
<ClCompile Include="..\filters\CopyFilterFactory.cpp" />
|
||||
<ClCompile Include="..\filters\DelayFilter.cpp" />
|
||||
<ClCompile Include="..\filters\DelayFilterFactory.cpp" />
|
||||
<ClCompile Include="..\filters\DeviceFilterFactory.cpp" />
|
||||
<ClCompile Include="..\filters\ExpressionFilterFactory.cpp" />
|
||||
<ClCompile Include="..\filters\GraphicEQFilter.cpp" />
|
||||
<ClCompile Include="..\filters\GraphicEQFilterFactory.cpp" />
|
||||
<ClCompile Include="..\filters\IfFilterFactory.cpp" />
|
||||
<ClCompile Include="..\filters\IIRFilter.cpp" />
|
||||
<ClCompile Include="..\filters\IIRFilterFactory.cpp" />
|
||||
<ClCompile Include="..\filters\IncludeFilterFactory.cpp" />
|
||||
<ClCompile Include="..\filters\PreampFilter.cpp" />
|
||||
<ClCompile Include="..\filters\PreampFilterFactory.cpp" />
|
||||
<ClCompile Include="..\filters\StageFilterFactory.cpp" />
|
||||
<ClCompile Include="..\helpers\ChannelHelper.cpp" />
|
||||
<ClCompile Include="..\helpers\GainIterator.cpp" />
|
||||
<ClCompile Include="..\helpers\LogHelper.cpp" />
|
||||
<ClCompile Include="..\helpers\MemoryHelper.cpp" />
|
||||
<ClCompile Include="..\helpers\RegistryHelper.cpp" />
|
||||
<ClCompile Include="..\helpers\StringHelper.cpp" />
|
||||
<ClCompile Include="..\IFilter.cpp" />
|
||||
<ClCompile Include="..\libHybridConv-0.1.1\libHybridConv_eapo.cpp" />
|
||||
<ClCompile Include="..\parser\RegexFunctions.cpp" />
|
||||
<ClCompile Include="..\parser\RegistryFunctions.cpp" />
|
||||
<ClCompile Include="..\parser\StringOperators.cpp" />
|
||||
<ClCompile Include="..\stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\VoicemeeterAPOInfo.cpp" />
|
||||
<ClCompile Include="VoicemeeterClient.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="VoicemeeterClient.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,239 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="helpers">
|
||||
<UniqueIdentifier>{0e9ead24-f831-4803-ab47-9b5208987e65}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="filters">
|
||||
<UniqueIdentifier>{e112c6dd-61fc-4742-808b-298e228688ed}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="parser">
|
||||
<UniqueIdentifier>{171427eb-7308-4b30-88c5-27068dd8a4f2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="libHybridConv-0.1.1">
|
||||
<UniqueIdentifier>{898022d7-bfa6-4240-b443-e82e638cf0f6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\helpers\RegistryHelper.h">
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VoicemeeterClient.h" />
|
||||
<ClInclude Include="..\helpers\StringHelper.h">
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\stdafx.h" />
|
||||
<ClInclude Include="..\..\..\..\..\Users\Jonas\Downloads\VoicemeeterRemoteAPI_Pack6\VoicemeeterRemote.h" />
|
||||
<ClInclude Include="..\FilterConfiguration.h" />
|
||||
<ClInclude Include="..\FilterEngine.h" />
|
||||
<ClInclude Include="..\filters\BiQuad.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\BiQuadFilter.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\BiQuadFilterFactory.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\ChannelFilter.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\ChannelFilterFactory.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\ConvolutionFilter.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\ConvolutionFilterFactory.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\CopyFilter.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\CopyFilterFactory.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\DelayFilter.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\DelayFilterFactory.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\DeviceFilterFactory.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\ExpressionFilterFactory.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\GraphicEQFilter.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\GraphicEQFilterFactory.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\IfFilterFactory.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\IIRFilter.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\IIRFilterFactory.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\IncludeFilterFactory.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\PreampFilter.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\PreampFilterFactory.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\filters\StageFilterFactory.h">
|
||||
<Filter>filters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\parser\RegexFunctions.h">
|
||||
<Filter>parser</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\parser\RegistryFunctions.h">
|
||||
<Filter>parser</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\parser\StringOperators.h">
|
||||
<Filter>parser</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\libHybridConv-0.1.1\libHybridConv_eapo.h">
|
||||
<Filter>libHybridConv-0.1.1</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\IFilter.h" />
|
||||
<ClInclude Include="..\IFilterFactory.h" />
|
||||
<ClInclude Include="..\helpers\MemoryHelper.h">
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\helpers\LogHelper.h">
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\helpers\GainIterator.h">
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\helpers\ChannelHelper.h">
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="..\VoicemeeterAPOInfo.h" />
|
||||
<ClInclude Include="..\AbstractAPOInfo.h" />
|
||||
<ClInclude Include="..\helpers\ScopeGuard.h">
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\helpers\UncaughtExceptions.h">
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\helpers\RegistryHelper.cpp">
|
||||
<Filter>helpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VoicemeeterClient.cpp" />
|
||||
<ClCompile Include="..\helpers\StringHelper.cpp">
|
||||
<Filter>helpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\stdafx.cpp" />
|
||||
<ClCompile Include="..\FilterConfiguration.cpp" />
|
||||
<ClCompile Include="..\FilterEngine.cpp" />
|
||||
<ClCompile Include="..\filters\BiQuad.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\BiQuadFilter.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\BiQuadFilterFactory.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\ChannelFilter.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\ChannelFilterFactory.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\ConvolutionFilter.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\ConvolutionFilterFactory.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\CopyFilter.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\CopyFilterFactory.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\DelayFilter.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\DelayFilterFactory.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\DeviceFilterFactory.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\ExpressionFilterFactory.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\GraphicEQFilter.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\GraphicEQFilterFactory.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\IfFilterFactory.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\IIRFilter.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\IIRFilterFactory.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\IncludeFilterFactory.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\PreampFilter.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\PreampFilterFactory.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filters\StageFilterFactory.cpp">
|
||||
<Filter>filters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\parser\RegexFunctions.cpp">
|
||||
<Filter>parser</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\parser\RegistryFunctions.cpp">
|
||||
<Filter>parser</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\parser\StringOperators.cpp">
|
||||
<Filter>parser</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libHybridConv-0.1.1\libHybridConv_eapo.cpp">
|
||||
<Filter>libHybridConv-0.1.1</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\IFilter.cpp" />
|
||||
<ClCompile Include="..\helpers\MemoryHelper.cpp">
|
||||
<Filter>helpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\helpers\LogHelper.cpp">
|
||||
<Filter>helpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\helpers\GainIterator.cpp">
|
||||
<Filter>helpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\helpers\ChannelHelper.cpp">
|
||||
<Filter>helpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\VoicemeeterAPOInfo.cpp" />
|
||||
<ClCompile Include="..\AbstractAPOInfo.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="VoicemeeterClient.rc" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,775 @@
|
||||
/******************************************************************************/
|
||||
/* Voicemeeter Remote API. V.Burel©2015 */
|
||||
/******************************************************************************/
|
||||
/* This Library allows communication with Voicemeeter Applications */
|
||||
/* 4 Client Applications can be connected to remote Voicemeeter. */
|
||||
/******************************************************************************/
|
||||
/* */
|
||||
/* OFFICIAL LINK : WWW.VOICEMEETER.COM */
|
||||
/* */
|
||||
/******************************************************************************/
|
||||
/* COPYRIGHT: Vincent Burel(c)2015 All Rights Reserved */
|
||||
/******************************************************************************/
|
||||
/* LICENSING: This header file and VoicemeeterRemote.dll are made available */
|
||||
/* for evaluation and testing purpose only (to make demo and proof */
|
||||
/* of concept). */
|
||||
/* */
|
||||
/* for any commercial exploitation or to get specific support, */
|
||||
/* a commercial license needs to be purchased. thanks to contact */
|
||||
/* us by e-mail (get our contact on www.vb-audio.com). */
|
||||
/******************************************************************************/
|
||||
/* long = 32 bit integer */
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
#ifndef __VOICEMEETER_REMOTE_H__
|
||||
#define __VOICEMEETER_REMOTE_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define VBVMR_RESULT_OK 0
|
||||
|
||||
/******************************************************************************/
|
||||
/* */
|
||||
/* Login */
|
||||
/* */
|
||||
/******************************************************************************/
|
||||
|
||||
/** @name Communication Login / logout
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
@brief Open Communication Pipe With Voicemeeter (typically called on software startup).
|
||||
@return : 0: OK (no error).
|
||||
1: OK but Voicemeeter Application not launched.
|
||||
-1: cannot get client (unexpected)
|
||||
-2: unexpected login (logout was expected before).
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_Login(void);
|
||||
|
||||
/**
|
||||
@brief Close Communication Pipe With Voicemeeter (typically called on software end).
|
||||
@return : 0 if ok.
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_Logout(void);
|
||||
|
||||
|
||||
/**
|
||||
@brief Run Voicemeeter Application (get installation directory and run Voicemeeter Application).
|
||||
@param vType : Voicemeeter type (1 = Voicemeeter, 2= Voicemeeter Banana).
|
||||
@return : 0: Ok.
|
||||
-1: not installed
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_RunVoicemeeter(long vType);
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* */
|
||||
/* General Information */
|
||||
/* */
|
||||
/******************************************************************************/
|
||||
|
||||
/** @name General Information
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
@brief Get Voicemeeter Type
|
||||
@param pType : Pointer on 32bit long receiving the type (1 = Voicemeeter, 2= Voicemeeter Banana).
|
||||
|
||||
VOICEMEETER STRIP/BUS INDEX ASSIGNMENT
|
||||
|
||||
| Strip 1 | Strip 2 |Virtual Input| BUS A | BUS B |
|
||||
+---------+---------+-------------+---------+---------+
|
||||
| 0 | 1 | 2 | 0 | 1 |
|
||||
|
||||
VOICEMEETER BANANA STRIP/BUS INDEX ASSIGNMENT
|
||||
|
||||
| Strip 1 | Strip 2 | Strip 2 |Virtual Input|Virtual AUX|BUS A1|BUS A2|BUS A3|BUS B1|BUS B2|
|
||||
+---------+---------+---------+-------------+-----------+------+------+------+------+------+
|
||||
| 0 | 1 | 2 | 3 | 4 | 0 | 1 | 2 | 3 | 4 |
|
||||
|
||||
|
||||
|
||||
@return : 0: OK (no error).
|
||||
-1: cannot get client (unexpected)
|
||||
-2: no server.
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_GetVoicemeeterType(long * pType);
|
||||
|
||||
/**
|
||||
@brief Get Voicemeeter Version
|
||||
@param pType : Pointer on 32bit integer receiving the version (v1.v2.v3.v4)
|
||||
v1 = (version & 0xFF000000)>>24;
|
||||
v2 = (version & 0x00FF0000)>>16;
|
||||
v3 = (version & 0x0000FF00)>>8;
|
||||
v4 = version & 0x000000FF;
|
||||
|
||||
@return : 0: OK (no error).
|
||||
-1: cannot get client (unexpected)
|
||||
-2: no server.
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_GetVoicemeeterVersion(long * pVersion);
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* */
|
||||
/* Get parameters */
|
||||
/* */
|
||||
/******************************************************************************/
|
||||
|
||||
/** @name Getting Parameters
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
@brief Check if parameters have changed.
|
||||
Call this function periodically (typically every 10 or 20ms).
|
||||
(this function must be called from one thread only)
|
||||
|
||||
@return: 0: no new paramters.
|
||||
1: New parameters -> update your display.
|
||||
-1: error (unexpected)
|
||||
-2: no server.
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_IsParametersDirty(void);
|
||||
|
||||
/**
|
||||
@brief get parameter value.
|
||||
@param szParamName : Null Terminal ASCII String giving the name of the parameter (see parameters name table)
|
||||
@param pValue : Pointer on float (32bit float by reference) receiving the wanted value.
|
||||
@return : 0: OK (no error).
|
||||
-1: error
|
||||
-2: no server.
|
||||
-3: unknown parameter
|
||||
-5: structure mismatch
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_GetParameterFloat(char * szParamName, float * pValue);
|
||||
|
||||
/**
|
||||
@brief get parameter value.
|
||||
@param szParamName : Null Terminal ASCII String giving the name of the parameter (see parameters name table)
|
||||
@param pValue : Pointer on String (512 char or wchar) receiving the wanted value.
|
||||
@return : 0: OK (no error).
|
||||
-1: error
|
||||
-2: no server.
|
||||
-3: unknown parameter
|
||||
-5: structure mismatch
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_GetParameterStringA(char * szParamName, char * szString);
|
||||
long __stdcall VBVMR_GetParameterStringW(char * szParamName, unsigned short * wszString);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* */
|
||||
/* Get levels */
|
||||
/* */
|
||||
/******************************************************************************/
|
||||
|
||||
/** @name Getting RT Data
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
@brief Get Current levels.
|
||||
(this function must be called from one thread only)
|
||||
|
||||
@param nType: 0= pre fader input levels.
|
||||
1= post fader input levels.
|
||||
2= post Mute input levels.
|
||||
3= output levels.
|
||||
|
||||
@param nuChannel: audio channel zero based index
|
||||
for input 0 = in#1 left, 1= in#1 Right, etc...
|
||||
for output 0 = busA ch1, 1 = busA ch2...
|
||||
|
||||
VOICEMEETER CHANNEL ASSIGNMENT
|
||||
|
||||
| Strip 1 | Strip 2 | Virtual Input |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 |
|
||||
|
||||
| Output A1 / A2 | Virtual Output |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 |
|
||||
|
||||
VOICEMEETER BANANA CHANNEL ASSIGNMENT
|
||||
|
||||
| Strip 1 | Strip 2 | Strip 3 | Virtual Input | Virtual Input AUX |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
|
||||
|
||||
| Output A1 | Output A2 | Output A3 |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
|
||||
|
||||
| Virtual Output B1 | Virtual Output B2 |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
|
||||
|
||||
|
||||
@return : 0: OK (no error).
|
||||
-1: error
|
||||
-2: no server.
|
||||
-3: no level available
|
||||
-4: out of range
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_GetLevel(long nType, long nuChannel, float * pValue);
|
||||
|
||||
|
||||
/**
|
||||
@brief Get MIDI message from M.I.D.I. input device used by Voicemeeter M.I.D.I. mapping.
|
||||
(this function must be called from one thread only)
|
||||
|
||||
@param pMIDIBuffer: pointer on MIDI Buffer. Expected message size is below 4 bytes,
|
||||
but it's recommended to use 1024 Bytes local buffer to receive
|
||||
possible multiple M.I.D.I. event message in optimal way:
|
||||
unsigned char pBuffer[1024];
|
||||
|
||||
|
||||
@return : >0: number of bytes placed in buffer (2 or 3 byte for usual M.I.D.I. message)
|
||||
-1: error
|
||||
-2: no server.
|
||||
-5: no MIDI data
|
||||
-6: no MIDI data
|
||||
*/
|
||||
|
||||
|
||||
long __stdcall VBVMR_GetMidiMessage(unsigned char *pMIDIBuffer, long nbByteMax);
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* */
|
||||
/* Set Parameters */
|
||||
/* */
|
||||
/******************************************************************************/
|
||||
|
||||
/** @name Setting Parameters
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
@brief Set a single float 32 bits parameters .
|
||||
@param szParamName : Null Terminal ASCII String giving the name of the parameter (see parameters name table)
|
||||
example:
|
||||
Strip[1].gain
|
||||
Strip[0].mute
|
||||
Bus[0].gain
|
||||
Bus[0].eq.channel[0].cell[0].gain
|
||||
|
||||
@param pValue : float 32bit containing the new value.
|
||||
@return : 0: OK (no error).
|
||||
-1: error
|
||||
-2: no server.
|
||||
-3: unknown parameter
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_SetParameterFloat(char * szParamName, float Value);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Set a single string parameters .
|
||||
@param szParamName : Null Terminal ASCII String giving the name of the parameter (see parameters name table)
|
||||
example:
|
||||
Strip[1].name
|
||||
Strip[0].device.mme
|
||||
Bus[0].device.asio
|
||||
|
||||
@param szString : zero terminal string.
|
||||
@return : 0: OK (no error).
|
||||
-1: error
|
||||
-2: no server.
|
||||
-3: unknown parameter
|
||||
|
||||
*/
|
||||
|
||||
|
||||
long __stdcall VBVMR_SetParameterStringA(char * szParamName, char * szString);
|
||||
long __stdcall VBVMR_SetParameterStringW(char * szParamName, unsigned short * wszString);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Set one or several parameters by a script ( < 48 kB ).
|
||||
@param szParamName : Null Terminal ASCII String giving the script
|
||||
(script allows to change several parameters in the same time - SYNCHRO).
|
||||
Possible Instuction separators: ',' ';' or '\n'(CR)
|
||||
EXAMPLE:
|
||||
"Strip[0].gain = -6.0
|
||||
Strip[0].A1 = 0
|
||||
Strip[0].B1 = 1
|
||||
Strip[1].gain = -6.0
|
||||
Strip[2].gain = 0.0
|
||||
Strip[3].name = "Skype Caller" "
|
||||
|
||||
@return : 0: OK (no error).
|
||||
>0: number of line causing script error.
|
||||
-1: error
|
||||
-2: no server.
|
||||
-3: unexpected error
|
||||
-4: unexpected error
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_SetParameters(char * szParamScript);
|
||||
long __stdcall VBVMR_SetParametersW(unsigned short * szParamScript);
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* DEVICES ENUMERATOR */
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
/** @name Device Enumeration Functions
|
||||
* @{ */
|
||||
|
||||
#define VBVMR_DEVTYPE_MME 1
|
||||
#define VBVMR_DEVTYPE_WDM 3
|
||||
#define VBVMR_DEVTYPE_KS 4
|
||||
#define VBVMR_DEVTYPE_ASIO 5
|
||||
|
||||
/**
|
||||
@brief Get number of Audio Output Device available on the system
|
||||
@return : return number of device found.
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_Output_GetDeviceNumber(void);
|
||||
|
||||
/**
|
||||
@brief Return pointer on Output Device Descriptor according index
|
||||
@param zindex : zero based index
|
||||
@param nType : Pointer on 32bit long receiving the type (pointer can be NULL).
|
||||
@param szName : Pointer on string (256 char min) receiving the device name (pointer can be NULL).
|
||||
@param szHardwareId : Pointer on string (256 char min) receiving the hardware ID (pointer can be NULL).
|
||||
@return : 0: OK (no error).
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_Output_GetDeviceDescA(long zindex, long * nType, char * szDeviceName, char * szHardwareId);
|
||||
long __stdcall VBVMR_Output_GetDeviceDescW(long zindex, long * nType, unsigned short * wszDeviceName, unsigned short * wszHardwareId);
|
||||
|
||||
/**
|
||||
@brief Get number of Audio Input Device available on the system
|
||||
@return : return number of device found.
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_Input_GetDeviceNumber(void);
|
||||
|
||||
/**
|
||||
@brief Return pointer on Input Device Descriptor according index
|
||||
@param zindex : zero based index
|
||||
@param nType : Pointer on 32bit long receiving the type (pointer can be NULL).
|
||||
@param szName : Pointer on string (256 char min) receiving the device name (pointer can be NULL).
|
||||
@param szHardwareId : Pointer on string (256 char min) receiving the hardware ID (pointer can be NULL).
|
||||
@return : 0: OK (no error).
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_Input_GetDeviceDescA(long zindex, long * nType, char * szDeviceName, char * szHardwareId);
|
||||
long __stdcall VBVMR_Input_GetDeviceDescW(long zindex, long * nType, unsigned short * wszDeviceName, unsigned short * wszHardwareId);
|
||||
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* VB-AUDIO CALLBACK */
|
||||
/******************************************************************************/
|
||||
/* 4x Functions to process all voicemeeter audio input and output channels */
|
||||
/* */
|
||||
/* VBVMR_AudioCallbackRegister :to register your audio callback(s) */
|
||||
/* VBVMR_AudioCallbackStart :to start the audio stream */
|
||||
/* VBVMR_AudioCallbackStop :to stop the audio stream */
|
||||
/* VBVMR_AudioCallbackUnregister :to unregister / Release callback(s) */
|
||||
/******************************************************************************/
|
||||
|
||||
/** @name VB-Audio Callback Functions
|
||||
* @{ */
|
||||
|
||||
|
||||
typedef struct tagVBVMR_AUDIOINFO
|
||||
{
|
||||
long samplerate;
|
||||
long nbSamplePerFrame;
|
||||
} VBVMR_T_AUDIOINFO, *VBVMR_PT_AUDIOINFO, *VBVMR_LPT_AUDIOINFO;
|
||||
|
||||
|
||||
typedef struct tagVBVMR_AUDIOBUFFER
|
||||
{
|
||||
long audiobuffer_sr; //Sampling Rate
|
||||
long audiobuffer_nbs; //number of sample per frame
|
||||
long audiobuffer_nbi; //number of inputs
|
||||
long audiobuffer_nbo; //number of outputs
|
||||
float * audiobuffer_r[128]; //nbi input pointers containing frame of nbs sample (of 32bits float)
|
||||
float * audiobuffer_w[128]; //nbo output pointers containing frame of nbs sample (of 32bits float)
|
||||
} VBVMR_T_AUDIOBUFFER, *VBVMR_PT_AUDIOBUFFER, *VBVMR_LPT_AUDIOBUFFER;
|
||||
|
||||
|
||||
/**
|
||||
@brief VB-AUDIO Callback is called for different task to Initialize, perform and end your process.
|
||||
VB-AUDIO Callback is part of single TIME CRITICAL Thread.
|
||||
VB-AUDIO Callback is non re-entrant (cannot be called while in process)
|
||||
VB-AUDIO Callback is supposed to be REAL TIME when called to process buffer.
|
||||
(it means that the process has to be performed as fast as possible, waiting cycles are forbidden.
|
||||
do not use O/S synchronization object, even Critical_Section can generate waiting cycle. Do not use
|
||||
system functions that can generate waiting cycle like display, disk or communication functions for example).
|
||||
|
||||
@param lpUser: User pointer given on callback registration.
|
||||
@param ncommand: reason why the callback is called.
|
||||
@param lpData: pointer on structure, pending on nCommand.
|
||||
@param nnn: additional data, unused
|
||||
|
||||
@return : 0: always 0 (unused).
|
||||
*/
|
||||
|
||||
|
||||
typedef long (__stdcall *T_VBVMR_VBAUDIOCALLBACK)(void * lpUser, long nCommand, void * lpData, long nnn);
|
||||
|
||||
|
||||
#define VBVMR_CBCOMMAND_STARTING 1 //command to initialize data according SR and buffer size
|
||||
//info = (VBVMR_LPT_AUDIOINFO)lpData
|
||||
|
||||
#define VBVMR_CBCOMMAND_ENDING 2 //command to release data
|
||||
#define VBVMR_CBCOMMAND_CHANGE 3 //If change in audio stream, you will have to restart audio
|
||||
|
||||
#define VBVMR_CBCOMMAND_BUFFER_IN 10 //input insert
|
||||
#define VBVMR_CBCOMMAND_BUFFER_OUT 11 //bus output insert
|
||||
#define VBVMR_CBCOMMAND_BUFFER_MAIN 20 //all i/o
|
||||
//audiobuffer = (VBVMR_LPT_AUDIOBUFFER)lpData
|
||||
//nnn = synchro = 1 if synchro with Voicemeeter
|
||||
|
||||
/*
|
||||
-----------------------------------------------------
|
||||
AUDIO BUFFER for VBVMR_CBCOMMAND_BUFFER_IN
|
||||
-----------------------------------------------------
|
||||
VOICEMEETER
|
||||
|
||||
| Strip 1 | Strip 2 | Virtual Input |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 |
|
||||
|
||||
VOICEMEETER BANANA
|
||||
|
||||
| Strip 1 | Strip 2 | Strip 3 | Virtual Input | Virtual Input AUX |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
|
||||
|
||||
VOICEMEETER 8
|
||||
|
||||
| Strip 1 | Strip 2 | Strip 3 | Strip 4 | Strip 5 | Virtual Input | Virtual Input AUX | Virtual Input 8 |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
|
||||
|
||||
|
||||
-----------------------------------------------------
|
||||
AUDIO BUFFER for VBVMR_CBCOMMAND_BUFFER_OUT
|
||||
-----------------------------------------------------
|
||||
VOICEMEETER
|
||||
|
||||
| Output A1 / A2 | Virtual Output |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 |
|
||||
|
||||
VOICEMEETER BANANA
|
||||
|
||||
| Output A1 | Output A2 | Output A3 |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
|
||||
|
||||
| Virtual Output B1 | Virtual Output B2 |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
|
||||
|
||||
|
||||
VOICEMEETER 8
|
||||
|
||||
| Output A1 | Output A2 | Output A3 | Output A4 | Output A5 |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
|
||||
|
||||
| Virtual Output B1 | Virtual Output B2 | Virtual Output B3 |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
|
||||
|
||||
|
||||
-----------------------------------------------------
|
||||
AUDIO BUFFER for VBVMR_CBCOMMAND_BUFFER_MAIN
|
||||
-----------------------------------------------------
|
||||
VOICEMEETER
|
||||
|
||||
| Strip 1 | Strip 2 | Virtual Input |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 |
|
||||
|
||||
| Output A1 / A2 | Virtual Output |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
|
||||
Output buffer provides outputs only:
|
||||
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 |
|
||||
|
||||
VOICEMEETER BANANA
|
||||
|
||||
| Strip 1 | Strip 2 | Strip 3 | Virtual Input | Virtual Input AUX |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
|
||||
|
||||
| Output A1 | Output A2 | Output A3 |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
|
||||
Output buffer provides outputs only:
|
||||
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
|
||||
|
||||
| Virtual Output B1 | Virtual Output B2 |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
|
||||
Output buffer provides outputs only:
|
||||
| 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
|
||||
|
||||
|
||||
VOICEMEETER 8
|
||||
|
||||
| Strip 1 | Strip 2 | Strip 3 | Strip 4 | Strip 5 | Virtual Input | Virtual Input AUX | Virtual Input 8 |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
|
||||
|
||||
| Output A1 | Output A2 | Output A3 | Output A4 | Output A5 |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 |
|
||||
Output buffer provides outputs only:
|
||||
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
|
||||
|
||||
| Virtual Output B1 | Virtual Output B2 | Virtual Output B3 |
|
||||
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|
||||
| 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 |
|
||||
Output buffer provides outputs only:
|
||||
| 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
@brief register your audio callback function to receive real time audio buffer
|
||||
it's possible to register up to 3x different Audio Callback in the same application or in
|
||||
3x different applications. In the same application, this is possible because Voicemeeter
|
||||
provides 3 kind of audio Streams:
|
||||
- AUDIO INPUT INSERT (to process all Voicemeeter inputs as insert)
|
||||
- AUDIO OUTPUT INSERT (to process all Voicemeeter BUS outputs as insert)
|
||||
- ALL AUDIO I/O (to process all Voicemeeter i/o).
|
||||
Note: a single callback can be used to receive the 3 possible audio streams.
|
||||
|
||||
@param mode : callback type (main, input or bus output) see define below
|
||||
@param pCallback : Pointer on your callback function.
|
||||
@param lpUser : user pointer (pointer that will be passed in callback first argument).
|
||||
@param szClientName[64]: IN: Name of the application registering the Callback.
|
||||
OUT: Name of the application already registered.
|
||||
@return : 0: OK (no error).
|
||||
-1: error
|
||||
1: callback already registered (by another application).
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_AudioCallbackRegister(long mode, T_VBVMR_VBAUDIOCALLBACK pCallback, void * lpUser, char szClientName[64]);
|
||||
|
||||
#define VBVMR_AUDIOCALLBACK_IN 0x00000001 //to process input insert
|
||||
#define VBVMR_AUDIOCALLBACK_OUT 0x00000002 //to process output bus insert
|
||||
#define VBVMR_AUDIOCALLBACK_MAIN 0x00000004 //to receive all i/o
|
||||
|
||||
/**
|
||||
@brief Start / Stop Audio processing
|
||||
|
||||
he Callback will be called with
|
||||
@return : 0: OK (no error).
|
||||
-1: error
|
||||
-2: no callback registred.
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_AudioCallbackStart(void);
|
||||
long __stdcall VBVMR_AudioCallbackStop(void);
|
||||
|
||||
|
||||
/**
|
||||
@brief unregister your callback to release voicemeeter virtual driver
|
||||
(this function will automatically call VBVMR_AudioCallbackStop() function)
|
||||
@param pCallback : Pointer on your callback function.
|
||||
@return : 0: OK (no error).
|
||||
-1: error
|
||||
1: callback already unregistered.
|
||||
*/
|
||||
|
||||
long __stdcall VBVMR_AudioCallbackUnregister(void);
|
||||
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* 'C' STRUCTURED INTERFACE */
|
||||
/******************************************************************************/
|
||||
|
||||
typedef long (__stdcall *T_VBVMR_Login)(void);
|
||||
typedef long (__stdcall *T_VBVMR_Logout)(void);
|
||||
typedef long (__stdcall *T_VBVMR_RunVoicemeeter)(long vType);
|
||||
|
||||
typedef long (__stdcall *T_VBVMR_GetVoicemeeterType)(long * pType);
|
||||
typedef long (__stdcall *T_VBVMR_GetVoicemeeterVersion)(long * pVersion);
|
||||
|
||||
typedef long (__stdcall *T_VBVMR_IsParametersDirty)(void);
|
||||
typedef long (__stdcall *T_VBVMR_GetParameterFloat)(char * szParamName, float * pValue);
|
||||
typedef long (__stdcall *T_VBVMR_GetParameterStringA)(char * szParamName, char * szString);
|
||||
typedef long (__stdcall *T_VBVMR_GetParameterStringW)(char * szParamName, unsigned short * wszString);
|
||||
|
||||
|
||||
typedef long (__stdcall *T_VBVMR_GetLevel)(long nType, long nuChannel, float * pValue);
|
||||
typedef long (__stdcall *T_VBVMR_GetMidiMessage)(unsigned char *pMIDIBuffer, long nbByteMax);
|
||||
|
||||
typedef long (__stdcall *T_VBVMR_SetParameterFloat)(char * szParamName, float Value);
|
||||
typedef long (__stdcall *T_VBVMR_SetParameters)(char * szParamScript);
|
||||
typedef long (__stdcall *T_VBVMR_SetParametersW)(unsigned short * szParamScript);
|
||||
typedef long (__stdcall *T_VBVMR_SetParameterStringA)(char * szParamName, char * szString);
|
||||
typedef long (__stdcall *T_VBVMR_SetParameterStringW)(char * szParamName, unsigned short * wszString);
|
||||
|
||||
typedef long (__stdcall *T_VBVMR_Output_GetDeviceNumber)(void);
|
||||
typedef long (__stdcall *T_VBVMR_Output_GetDeviceDescA)(long zindex, long * nType, char * szDeviceName, char * szHardwareId);
|
||||
typedef long (__stdcall *T_VBVMR_Output_GetDeviceDescW)(long zindex, long * nType, unsigned short * wszDeviceName, unsigned short * wszHardwareId);
|
||||
typedef long (__stdcall *T_VBVMR_Input_GetDeviceNumber)(void);
|
||||
typedef long (__stdcall *T_VBVMR_Input_GetDeviceDescA)(long zindex, long * nType, char * szDeviceName, char * szHardwareId);
|
||||
typedef long (__stdcall *T_VBVMR_Input_GetDeviceDescW)(long zindex, long * nType, unsigned short * wszDeviceName, unsigned short * wszHardwareId);
|
||||
|
||||
typedef long (__stdcall *T_VBVMR_AudioCallbackRegister)(long mode, T_VBVMR_VBAUDIOCALLBACK pCallback, void * lpUser, char szClientName[64]);
|
||||
typedef long (__stdcall *T_VBVMR_AudioCallbackStart)(void);
|
||||
typedef long (__stdcall *T_VBVMR_AudioCallbackStop)(void);
|
||||
typedef long (__stdcall *T_VBVMR_AudioCallbackUnregister)(void);
|
||||
|
||||
|
||||
typedef struct tagVBVMR_INTERFACE
|
||||
{
|
||||
T_VBVMR_Login VBVMR_Login;
|
||||
T_VBVMR_Logout VBVMR_Logout;
|
||||
T_VBVMR_RunVoicemeeter VBVMR_RunVoicemeeter;
|
||||
T_VBVMR_GetVoicemeeterType VBVMR_GetVoicemeeterType;
|
||||
T_VBVMR_GetVoicemeeterVersion VBVMR_GetVoicemeeterVersion;
|
||||
T_VBVMR_IsParametersDirty VBVMR_IsParametersDirty;
|
||||
T_VBVMR_GetParameterFloat VBVMR_GetParameterFloat;
|
||||
T_VBVMR_GetParameterStringA VBVMR_GetParameterStringA;
|
||||
T_VBVMR_GetParameterStringW VBVMR_GetParameterStringW;
|
||||
|
||||
T_VBVMR_GetLevel VBVMR_GetLevel;
|
||||
T_VBVMR_GetMidiMessage VBVMR_GetMidiMessage;
|
||||
|
||||
T_VBVMR_SetParameterFloat VBVMR_SetParameterFloat;
|
||||
T_VBVMR_SetParameters VBVMR_SetParameters;
|
||||
T_VBVMR_SetParametersW VBVMR_SetParametersW;
|
||||
T_VBVMR_SetParameterStringA VBVMR_SetParameterStringA;
|
||||
T_VBVMR_SetParameterStringW VBVMR_SetParameterStringW;
|
||||
|
||||
T_VBVMR_Output_GetDeviceNumber VBVMR_Output_GetDeviceNumber;
|
||||
T_VBVMR_Output_GetDeviceDescA VBVMR_Output_GetDeviceDescA;
|
||||
T_VBVMR_Output_GetDeviceDescW VBVMR_Output_GetDeviceDescW;
|
||||
T_VBVMR_Input_GetDeviceNumber VBVMR_Input_GetDeviceNumber;
|
||||
T_VBVMR_Input_GetDeviceDescA VBVMR_Input_GetDeviceDescA;
|
||||
T_VBVMR_Input_GetDeviceDescW VBVMR_Input_GetDeviceDescW;
|
||||
|
||||
T_VBVMR_AudioCallbackRegister VBVMR_AudioCallbackRegister;
|
||||
T_VBVMR_AudioCallbackStart VBVMR_AudioCallbackStart;
|
||||
T_VBVMR_AudioCallbackStop VBVMR_AudioCallbackStop;
|
||||
T_VBVMR_AudioCallbackUnregister VBVMR_AudioCallbackUnregister;
|
||||
|
||||
} T_VBVMR_INTERFACE, *PT_VBVMR_INTERFACE, *LPT_VBVMR_INTERFACE;
|
||||
|
||||
#ifdef VBUSE_LOCALLIB
|
||||
// internal used (not public)
|
||||
void __stdcall VBVMR_SetHinstance(HINSTANCE hinst);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__VOICEMEETER_REMOTE_H__*/
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by VoicemeeterClient.rc
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
@@ -7,7 +7,7 @@ if %ERRORLEVEL% GEQ 1 goto done
|
||||
if not exist build-Editor-Desktop_Qt_5_7_MSVC2013_32bit-Release mkdir build-Editor-Desktop_Qt_5_7_MSVC2013_32bit-Release
|
||||
cd build-Editor-Desktop_Qt_5_7_MSVC2013_32bit-Release
|
||||
call "%VCINSTALLDIR%vcvarsall.bat" x86
|
||||
"C:\Qt\5.7\msvc2013\bin\qmake.exe" ..\Editor\Editor.pro -r -spec win32-msvc2013
|
||||
"C:\Qt\5.7\msvc2013\bin\qmake.exe" ..\Editor\Editor.pro -r -spec win32-msvc2013 "CONFIG+=release"
|
||||
"C:\Qt\Tools\QtCreator\bin\jom.exe" clean
|
||||
"C:\Qt\Tools\QtCreator\bin\jom.exe"
|
||||
if %ERRORLEVEL% GEQ 1 goto done
|
||||
@@ -16,7 +16,7 @@ cd..
|
||||
if not exist build-Editor-Desktop_Qt_5_7_MSVC2013_64bit-Release mkdir build-Editor-Desktop_Qt_5_7_MSVC2013_64bit-Release
|
||||
cd build-Editor-Desktop_Qt_5_7_MSVC2013_64bit-Release
|
||||
call "%VCINSTALLDIR%vcvarsall.bat" amd64
|
||||
"C:\Qt\5.7\msvc2013_64\bin\qmake.exe" ..\Editor\Editor.pro -r -spec win32-msvc2013
|
||||
"C:\Qt\5.7\msvc2013_64\bin\qmake.exe" ..\Editor\Editor.pro -r -spec win32-msvc2013 "CONFIG+=release"
|
||||
"C:\Qt\Tools\QtCreator\bin\jom.exe" clean
|
||||
"C:\Qt\Tools\QtCreator\bin\jom.exe"
|
||||
if %ERRORLEVEL% GEQ 1 goto done
|
||||
|
||||
@@ -30,7 +30,7 @@ using namespace std;
|
||||
#ifndef NO_FILTERENGINE
|
||||
void DeviceFilterFactory::initialize(FilterEngine* engine)
|
||||
{
|
||||
deviceString = engine->getDeviceName() + L" " + engine->getConnectionName() + L" " + engine->getDeviceGuid();
|
||||
deviceString = engine->getDeviceString();
|
||||
|
||||
mup::ParserX* parser = engine->getParser();
|
||||
parser->DefineConst(L"deviceName", engine->getDeviceName());
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
#ifndef SCOPEGUARD_H
|
||||
#define SCOPEGUARD_H
|
||||
|
||||
// Taken from "Declarative Control Flow" (CppCon 2015)
|
||||
// adjusted to work with Visual C++ 2013
|
||||
|
||||
#include <exception>
|
||||
#include <utility>
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
||||
#define noexcept
|
||||
#endif
|
||||
#include "UncaughtExceptions.h"
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
||||
#undef noexcept
|
||||
#endif
|
||||
|
||||
#define CONCATENATE_IMPL(s1, s2) s1 ## s2
|
||||
#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2)
|
||||
#ifdef __COUNTER__
|
||||
#define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __COUNTER__)
|
||||
#else
|
||||
#define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __LINE__)
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
enum class ScopeGuardOnExit
|
||||
{
|
||||
};
|
||||
|
||||
enum class ScopeGuardOnFail
|
||||
{
|
||||
};
|
||||
|
||||
enum class ScopeGuardOnSuccess
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Fun> class ScopeGuard
|
||||
{
|
||||
public:
|
||||
ScopeGuard(Fun&& fn)
|
||||
: fn(std::move(fn))
|
||||
{
|
||||
}
|
||||
~ScopeGuard()
|
||||
{
|
||||
fn();
|
||||
}
|
||||
|
||||
private:
|
||||
Fun fn;
|
||||
};
|
||||
|
||||
class UncaughtExceptionCounter
|
||||
{
|
||||
int exceptionCount_;
|
||||
|
||||
public:
|
||||
UncaughtExceptionCounter()
|
||||
: exceptionCount_(folly::uncaught_exceptions())
|
||||
{
|
||||
}
|
||||
|
||||
bool newUncaughtException()
|
||||
{
|
||||
return folly::uncaught_exceptions() > exceptionCount_;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename FunctionType, bool executeOnException> class ScopeGuardForNewException
|
||||
{
|
||||
FunctionType function_;
|
||||
UncaughtExceptionCounter ec_;
|
||||
|
||||
public:
|
||||
explicit ScopeGuardForNewException(const FunctionType& fn)
|
||||
: function_(fn)
|
||||
{
|
||||
}
|
||||
|
||||
explicit ScopeGuardForNewException(FunctionType&& fn)
|
||||
: function_(std::move(fn))
|
||||
{
|
||||
}
|
||||
|
||||
~ScopeGuardForNewException()
|
||||
{
|
||||
if (executeOnException == ec_.newUncaughtException())
|
||||
{
|
||||
function_();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Fun> ScopeGuard<Fun> operator+(ScopeGuardOnExit, Fun&& fn)
|
||||
{
|
||||
return ScopeGuard<Fun>(std::forward<Fun>(fn));
|
||||
}
|
||||
|
||||
template<typename Fun> ScopeGuardForNewException<typename std::decay_t<Fun>, true> operator+(detail::ScopeGuardOnFail, Fun&& fn)
|
||||
{
|
||||
return ScopeGuardForNewException<typename std::decay_t<Fun>, true>(std::forward<Fun>(fn));
|
||||
}
|
||||
|
||||
template<typename Fun> ScopeGuardForNewException<typename std::decay_t<Fun>, false> operator+(detail::ScopeGuardOnSuccess, Fun&& fn)
|
||||
{
|
||||
return ScopeGuardForNewException<typename std::decay_t<Fun>, false>(std::forward<Fun>(fn));
|
||||
}
|
||||
}
|
||||
|
||||
#define SCOPE_FAIL auto ANONYMOUS_VARIABLE(SCOPE_FAIL_STATE) = ::detail::ScopeGuardOnFail() +[&]()
|
||||
#define SCOPE_SUCCESS auto ANONYMOUS_VARIABLE(SCOPE_FAIL_STATE) = ::detail::ScopeGuardOnSuccess() +[&]()
|
||||
#define SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) = ::detail::ScopeGuardOnExit() +[&]()
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2017 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <exception>
|
||||
|
||||
#if defined(__GNUG__) || defined(__CLANG__)
|
||||
#define FOLLY_EXCEPTION_COUNT_USE_CXA_GET_GLOBALS
|
||||
namespace __cxxabiv1 {
|
||||
// forward declaration (originally defined in unwind-cxx.h from from libstdc++)
|
||||
struct __cxa_eh_globals;
|
||||
// declared in cxxabi.h from libstdc++-v3
|
||||
extern "C" __cxa_eh_globals* __cxa_get_globals() noexcept;
|
||||
}
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1400) && \
|
||||
(_MSC_VER < 1900) // MSVC++ 8.0 or greater
|
||||
#define FOLLY_EXCEPTION_COUNT_USE_GETPTD
|
||||
// forward declaration (originally defined in mtdll.h from MSVCRT)
|
||||
struct _tiddata;
|
||||
extern "C" _tiddata* _getptd(); // declared in mtdll.h from MSVCRT
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1900) // MSVC++ 2015
|
||||
#define FOLLY_EXCEPTION_COUNT_USE_STD
|
||||
#else
|
||||
// Raise an error when trying to use this on unsupported platforms.
|
||||
#error "Unsupported platform, don't include this header."
|
||||
#endif
|
||||
|
||||
namespace folly {
|
||||
|
||||
/**
|
||||
* Returns the number of uncaught exceptions.
|
||||
*
|
||||
* This function is based on Evgeny Panasyuk's implementation from here:
|
||||
* http://fburl.com/15190026
|
||||
*/
|
||||
inline int uncaught_exceptions() noexcept {
|
||||
#if defined(FOLLY_EXCEPTION_COUNT_USE_CXA_GET_GLOBALS)
|
||||
// __cxa_get_globals returns a __cxa_eh_globals* (defined in unwind-cxx.h).
|
||||
// The offset below returns __cxa_eh_globals::uncaughtExceptions.
|
||||
return *(reinterpret_cast<unsigned int*>(static_cast<char*>(
|
||||
static_cast<void*>(__cxxabiv1::__cxa_get_globals())) + sizeof(void*)));
|
||||
#elif defined(FOLLY_EXCEPTION_COUNT_USE_GETPTD)
|
||||
// _getptd() returns a _tiddata* (defined in mtdll.h).
|
||||
// The offset below returns _tiddata::_ProcessingThrow.
|
||||
return *(reinterpret_cast<int*>(static_cast<char*>(
|
||||
static_cast<void*>(_getptd())) + sizeof(void*) * 28 + 0x4 * 8));
|
||||
#elif defined(FOLLY_EXCEPTION_COUNT_USE_STD)
|
||||
return std::uncaught_exceptions();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespaces
|
||||
Reference in new issue
Block a user