Added: VST Plugin support. Add and configure plugins via Configuration Editor. The plugin's architecture has to match the OS architecture, so most people will need 64-bit plugins. The subdirectory plugins is offered to put plugins into, but they can be opened from any directory with sufficient permissions.
Fixed: When trying to add a high-pass filter in the Configuration Editor, it was instead configured to be a low-pass filter.
This commit is contained in:
1 parent
989812ba36
commit
a24eaa0cd9
58 files changed
+3333
-150
No files matched your search
+70
-69
@@ -162,78 +162,79 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
PrecisionTimer timer;
|
PrecisionTimer timer;
|
||||||
timer.start();
|
timer.start();
|
||||||
|
|
||||||
FilterEngine engine;
|
|
||||||
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();
|
|
||||||
if (!verbose)
|
|
||||||
printf("\nLoading configuration took %g ms\n", initTime * 1000.0);
|
|
||||||
|
|
||||||
printf("\nProcessing %d frames from %d channel(s)\n", frameCount, channelCount);
|
|
||||||
|
|
||||||
timer.start();
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < frameCount; i += batchsize)
|
|
||||||
{
|
{
|
||||||
engine.process(buf2 + i * channelCount, buf + i * channelCount, min(batchsize, frameCount - i));
|
FilterEngine engine;
|
||||||
|
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();
|
||||||
|
if(!verbose)
|
||||||
|
printf("\nLoading configuration took %g ms\n", initTime * 1000.0);
|
||||||
|
|
||||||
|
printf("\nProcessing %d frames from %d channel(s)\n", frameCount, channelCount);
|
||||||
|
|
||||||
|
timer.start();
|
||||||
|
|
||||||
|
for(unsigned i = 0; i < frameCount; i += batchsize)
|
||||||
|
{
|
||||||
|
engine.process(buf2 + i * channelCount, buf + i * channelCount, min(batchsize, frameCount - i));
|
||||||
|
}
|
||||||
|
|
||||||
|
double time = timer.stop();
|
||||||
|
|
||||||
|
printf("%d samples processed in %f seconds\n", frameCount * channelCount, time);
|
||||||
|
printf("This is equivalent to %.2f%% CPU load (one core) when processing in real time\n", 100.0f * time / length);
|
||||||
|
|
||||||
|
unsigned clipCount = 0;
|
||||||
|
float max = 0;
|
||||||
|
for(unsigned i = 0; i < frameCount * channelCount; i++)
|
||||||
|
{
|
||||||
|
float f = fabs(buf2[i]);
|
||||||
|
if(f > max)
|
||||||
|
max = f;
|
||||||
|
if(f > 1.0f)
|
||||||
|
clipCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Max output level: %f (%f dB)", max, log10(max) * 20.0f);
|
||||||
|
if(clipCount > 0)
|
||||||
|
printf(" (%d samples clipped!)", clipCount);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
string output = outputArg.getValue();
|
||||||
|
if(output == "")
|
||||||
|
{
|
||||||
|
char temp[255];
|
||||||
|
GetTempPathA(sizeof(temp) / sizeof(wchar_t), temp);
|
||||||
|
|
||||||
|
output = temp;
|
||||||
|
output += "testout.wav";
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nWriting output to %s\n", output.c_str());
|
||||||
|
|
||||||
|
SF_INFO info = {frameCount, (int)sampleRate, (int)channelCount, SF_FORMAT_WAV | SF_FORMAT_PCM_16, 0};
|
||||||
|
SNDFILE* outFile = sf_open(output.c_str(), SFM_WRITE, &info);
|
||||||
|
if(outFile == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s", sf_strerror(outFile));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sf_count_t numWritten = 0;
|
||||||
|
while(numWritten < frameCount)
|
||||||
|
numWritten += sf_writef_float(outFile, buf2 + numWritten * channelCount, frameCount - numWritten);
|
||||||
|
|
||||||
|
sf_close(outFile);
|
||||||
|
outFile = NULL;
|
||||||
|
|
||||||
|
delete[]buf;
|
||||||
|
delete[]buf2;
|
||||||
}
|
}
|
||||||
|
|
||||||
double time = timer.stop();
|
|
||||||
|
|
||||||
printf("%d samples processed in %f seconds\n", frameCount * channelCount, time);
|
|
||||||
printf("This is equivalent to %.2f%% CPU load (one core) when processing in real time\n", 100.0f * time / length);
|
|
||||||
|
|
||||||
unsigned clipCount = 0;
|
|
||||||
float max = 0;
|
|
||||||
for (unsigned i = 0; i < frameCount * channelCount; i++)
|
|
||||||
{
|
|
||||||
float f = fabs(buf2[i]);
|
|
||||||
if (f > max)
|
|
||||||
max = f;
|
|
||||||
if (f > 1.0f)
|
|
||||||
clipCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Max output level: %f (%f dB)", max, log10(max) * 20.0f);
|
|
||||||
if (clipCount > 0)
|
|
||||||
printf(" (%d samples clipped!)", clipCount);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
string output = outputArg.getValue();
|
|
||||||
if (output == "")
|
|
||||||
{
|
|
||||||
char temp[255];
|
|
||||||
GetTempPathA(sizeof(temp) / sizeof(wchar_t), temp);
|
|
||||||
|
|
||||||
output = temp;
|
|
||||||
output += "testout.wav";
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\nWriting output to %s\n", output.c_str());
|
|
||||||
|
|
||||||
SF_INFO info = {frameCount, (int)sampleRate, (int)channelCount, SF_FORMAT_WAV | SF_FORMAT_PCM_16, 0};
|
|
||||||
SNDFILE* outFile = sf_open(output.c_str(), SFM_WRITE, &info);
|
|
||||||
if (outFile == NULL)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s", sf_strerror(outFile));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sf_count_t numWritten = 0;
|
|
||||||
while (numWritten < frameCount)
|
|
||||||
numWritten += sf_writef_float(outFile, buf2 + numWritten * channelCount, frameCount - numWritten);
|
|
||||||
|
|
||||||
sf_close(outFile);
|
|
||||||
outFile = NULL;
|
|
||||||
|
|
||||||
delete[]buf;
|
|
||||||
delete[]buf2;
|
|
||||||
|
|
||||||
if (!noPauseArg.getValue())
|
if (!noPauseArg.getValue())
|
||||||
system("pause");
|
system("pause");
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,7 @@
|
|||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>muparserxd.lib;version.lib;Shlwapi.lib;authz.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>muparserxd.lib;version.lib;Shlwapi.lib;authz.lib;crypt32.lib;dbghelp.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@@ -110,7 +110,7 @@
|
|||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>muparserxd.lib;version.lib;Shlwapi.lib;authz.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>muparserxd.lib;version.lib;Shlwapi.lib;authz.lib;crypt32.lib;dbghelp.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@@ -128,7 +128,7 @@
|
|||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>muparserx.lib;version.lib;Shlwapi.lib;authz.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>muparserx.lib;version.lib;Shlwapi.lib;authz.lib;crypt32.lib;dbghelp.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@@ -146,7 +146,7 @@
|
|||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>muparserx.lib;version.lib;Shlwapi.lib;authz.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>muparserx.lib;version.lib;Shlwapi.lib;authz.lib;crypt32.lib;dbghelp.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -174,12 +174,17 @@
|
|||||||
<ClCompile Include="..\filters\PreampFilter.cpp" />
|
<ClCompile Include="..\filters\PreampFilter.cpp" />
|
||||||
<ClCompile Include="..\filters\PreampFilterFactory.cpp" />
|
<ClCompile Include="..\filters\PreampFilterFactory.cpp" />
|
||||||
<ClCompile Include="..\filters\StageFilterFactory.cpp" />
|
<ClCompile Include="..\filters\StageFilterFactory.cpp" />
|
||||||
|
<ClCompile Include="..\filters\VSTPluginFilter.cpp" />
|
||||||
|
<ClCompile Include="..\filters\VSTPluginFilterFactory.cpp" />
|
||||||
|
<ClCompile Include="..\helpers\AbstractLibrary.cpp" />
|
||||||
<ClCompile Include="..\helpers\ChannelHelper.cpp" />
|
<ClCompile Include="..\helpers\ChannelHelper.cpp" />
|
||||||
<ClCompile Include="..\helpers\GainIterator.cpp" />
|
<ClCompile Include="..\helpers\GainIterator.cpp" />
|
||||||
<ClCompile Include="..\helpers\LogHelper.cpp" />
|
<ClCompile Include="..\helpers\LogHelper.cpp" />
|
||||||
<ClCompile Include="..\helpers\MemoryHelper.cpp" />
|
<ClCompile Include="..\helpers\MemoryHelper.cpp" />
|
||||||
<ClCompile Include="..\helpers\RegistryHelper.cpp" />
|
<ClCompile Include="..\helpers\RegistryHelper.cpp" />
|
||||||
<ClCompile Include="..\helpers\StringHelper.cpp" />
|
<ClCompile Include="..\helpers\StringHelper.cpp" />
|
||||||
|
<ClCompile Include="..\helpers\VSTPluginInstance.cpp" />
|
||||||
|
<ClCompile Include="..\helpers\VSTPluginLibrary.cpp" />
|
||||||
<ClCompile Include="..\IFilter.cpp" />
|
<ClCompile Include="..\IFilter.cpp" />
|
||||||
<ClCompile Include="..\libHybridConv-0.1.1\libHybridConv_eapo.cpp" />
|
<ClCompile Include="..\libHybridConv-0.1.1\libHybridConv_eapo.cpp" />
|
||||||
<ClCompile Include="..\parser\RegexFunctions.cpp" />
|
<ClCompile Include="..\parser\RegexFunctions.cpp" />
|
||||||
@@ -218,6 +223,9 @@
|
|||||||
<ClInclude Include="..\filters\PreampFilter.h" />
|
<ClInclude Include="..\filters\PreampFilter.h" />
|
||||||
<ClInclude Include="..\filters\PreampFilterFactory.h" />
|
<ClInclude Include="..\filters\PreampFilterFactory.h" />
|
||||||
<ClInclude Include="..\filters\StageFilterFactory.h" />
|
<ClInclude Include="..\filters\StageFilterFactory.h" />
|
||||||
|
<ClInclude Include="..\filters\VSTPluginFilter.h" />
|
||||||
|
<ClInclude Include="..\filters\VSTPluginFilterFactory.h" />
|
||||||
|
<ClInclude Include="..\helpers\AbstractLibrary.h" />
|
||||||
<ClInclude Include="..\helpers\ChannelHelper.h" />
|
<ClInclude Include="..\helpers\ChannelHelper.h" />
|
||||||
<ClInclude Include="..\helpers\GainIterator.h" />
|
<ClInclude Include="..\helpers\GainIterator.h" />
|
||||||
<ClInclude Include="..\helpers\LogHelper.h" />
|
<ClInclude Include="..\helpers\LogHelper.h" />
|
||||||
@@ -227,6 +235,8 @@
|
|||||||
<ClInclude Include="..\helpers\ScopeGuard.h" />
|
<ClInclude Include="..\helpers\ScopeGuard.h" />
|
||||||
<ClInclude Include="..\helpers\StringHelper.h" />
|
<ClInclude Include="..\helpers\StringHelper.h" />
|
||||||
<ClInclude Include="..\helpers\UncaughtExceptions.h" />
|
<ClInclude Include="..\helpers\UncaughtExceptions.h" />
|
||||||
|
<ClInclude Include="..\helpers\VSTPluginInstance.h" />
|
||||||
|
<ClInclude Include="..\helpers\VSTPluginLibrary.h" />
|
||||||
<ClInclude Include="..\IFilter.h" />
|
<ClInclude Include="..\IFilter.h" />
|
||||||
<ClInclude Include="..\IFilterFactory.h" />
|
<ClInclude Include="..\IFilterFactory.h" />
|
||||||
<ClInclude Include="..\libHybridConv-0.1.1\libHybridConv_eapo.h" />
|
<ClInclude Include="..\libHybridConv-0.1.1\libHybridConv_eapo.h" />
|
||||||
@@ -235,6 +245,9 @@
|
|||||||
<ClInclude Include="..\parser\StringOperators.h" />
|
<ClInclude Include="..\parser\StringOperators.h" />
|
||||||
<ClInclude Include="..\stdafx.h" />
|
<ClInclude Include="..\stdafx.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\EqualizerAPO.licenseheader" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
|||||||
@@ -102,6 +102,21 @@
|
|||||||
<Filter>filters</Filter>
|
<Filter>filters</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\stdafx.cpp" />
|
<ClCompile Include="..\stdafx.cpp" />
|
||||||
|
<ClCompile Include="..\helpers\AbstractLibrary.cpp">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\filters\VSTPluginFilter.cpp">
|
||||||
|
<Filter>filters</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\filters\VSTPluginFilterFactory.cpp">
|
||||||
|
<Filter>filters</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\helpers\VSTPluginLibrary.cpp">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\helpers\VSTPluginInstance.cpp">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\FilterEngine.h" />
|
<ClInclude Include="..\FilterEngine.h" />
|
||||||
@@ -214,6 +229,21 @@
|
|||||||
<ClInclude Include="..\helpers\UncaughtExceptions.h">
|
<ClInclude Include="..\helpers\UncaughtExceptions.h">
|
||||||
<Filter>helpers</Filter>
|
<Filter>helpers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\helpers\AbstractLibrary.h">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\filters\VSTPluginFilter.h">
|
||||||
|
<Filter>filters</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\filters\VSTPluginFilterFactory.h">
|
||||||
|
<Filter>filters</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\helpers\VSTPluginLibrary.h">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\helpers\VSTPluginInstance.h">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="parser">
|
<Filter Include="parser">
|
||||||
@@ -229,4 +259,7 @@
|
|||||||
<UniqueIdentifier>{35b3b6f1-e4df-4214-bd4c-fa058942e547}</UniqueIdentifier>
|
<UniqueIdentifier>{35b3b6f1-e4df-4214-bd4c-fa058942e547}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\EqualizerAPO.licenseheader" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -53,6 +53,7 @@
|
|||||||
<ResourceCompile Include="Configurator.rc" />
|
<ResourceCompile Include="Configurator.rc" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<None Include="..\EqualizerAPO.licenseheader" />
|
||||||
<None Include="Configurator.ico" />
|
<None Include="Configurator.ico" />
|
||||||
<None Include="small.ico" />
|
<None Include="small.ico" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -54,6 +54,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Configurator.ico" />
|
<None Include="Configurator.ico" />
|
||||||
<None Include="small.ico" />
|
<None Include="small.ico" />
|
||||||
|
<None Include="..\EqualizerAPO.licenseheader" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Manifest Include="Configurator.exe.manifest" />
|
<Manifest Include="Configurator.exe.manifest" />
|
||||||
|
|||||||
+27
-14
@@ -109,7 +109,7 @@ double AnalysisThread::getProcessingTime() const
|
|||||||
return processingTime;
|
return processingTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AnalysisThread::getProcessedFrames() const
|
unsigned AnalysisThread::getProcessedFrames() const
|
||||||
{
|
{
|
||||||
return processedFrames;
|
return processedFrames;
|
||||||
}
|
}
|
||||||
@@ -153,6 +153,7 @@ void AnalysisThread::run()
|
|||||||
unsigned sampleRate = device->getSampleRate();
|
unsigned sampleRate = device->getSampleRate();
|
||||||
|
|
||||||
qint64 startTime = timer.nsecsElapsed();
|
qint64 startTime = timer.nsecsElapsed();
|
||||||
|
|
||||||
FilterEngine engine;
|
FilterEngine engine;
|
||||||
engine.setDeviceInfo(device->isInput(), true, device->getDeviceName(), device->getConnectionName(), device->getDeviceGuid(), device->getDeviceString());
|
engine.setDeviceInfo(device->isInput(), true, device->getDeviceName(), device->getConnectionName(), device->getDeviceGuid(), device->getDeviceString());
|
||||||
engine.initialize(sampleRate, channelCount, channelCount, channelCount, channelMask, frameCount, configPath.toStdWString());
|
engine.initialize(sampleRate, channelCount, channelCount, channelCount, channelMask, frameCount, configPath.toStdWString());
|
||||||
@@ -193,8 +194,9 @@ void AnalysisThread::run()
|
|||||||
int latency = 0;
|
int latency = 0;
|
||||||
int startFrame = -1;
|
int startFrame = -1;
|
||||||
double processingTime = 0.0;
|
double processingTime = 0.0;
|
||||||
int processedFrames = 0;
|
unsigned processedFrames = 0;
|
||||||
while (true)
|
// stop searching for startFrame after 10 seconds of audio data
|
||||||
|
while (processedFrames < 10 * sampleRate)
|
||||||
{
|
{
|
||||||
qint64 startTime = timer.nsecsElapsed();
|
qint64 startTime = timer.nsecsElapsed();
|
||||||
engine.process(buf2, buf, frameCount);
|
engine.process(buf2, buf, frameCount);
|
||||||
@@ -240,20 +242,31 @@ void AnalysisThread::run()
|
|||||||
if (startFrame == -1)
|
if (startFrame == -1)
|
||||||
latency += frameCount;
|
latency += frameCount;
|
||||||
}
|
}
|
||||||
latency += startFrame;
|
|
||||||
|
|
||||||
fftwf_execute(planForward);
|
double peakGain;
|
||||||
|
if (startFrame != -1)
|
||||||
double peakGain = -DBL_MAX;
|
|
||||||
|
|
||||||
for (int i = 0; i < frameCount / 2; i++)
|
|
||||||
{
|
{
|
||||||
float sqrGain = freqData[i][0] * freqData[i][0] + freqData[i][1] * freqData[i][1];
|
latency += startFrame;
|
||||||
if (sqrGain > peakGain)
|
|
||||||
peakGain = sqrGain;
|
fftwf_execute(planForward);
|
||||||
|
|
||||||
|
peakGain = -DBL_MAX;
|
||||||
|
|
||||||
|
for (int i = 0; i < frameCount / 2; i++)
|
||||||
|
{
|
||||||
|
float sqrGain = freqData[i][0] * freqData[i][0] + freqData[i][1] * freqData[i][1];
|
||||||
|
if (sqrGain > peakGain)
|
||||||
|
peakGain = sqrGain;
|
||||||
|
}
|
||||||
|
peakGain = sqrt(peakGain);
|
||||||
|
peakGain = log10(peakGain) * 20.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
latency = 0;
|
||||||
|
peakGain = -numeric_limits<double>::infinity();
|
||||||
|
memset(freqData, 0, frameCount * sizeof(fftwf_complex));
|
||||||
}
|
}
|
||||||
peakGain = sqrt(peakGain);
|
|
||||||
peakGain = log10(peakGain) * 20.0;
|
|
||||||
|
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
if (this->freqDataLength != frameCount)
|
if (this->freqDataLength != frameCount)
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public:
|
|||||||
int getLatency() const;
|
int getLatency() const;
|
||||||
double getInitializationTime() const;
|
double getInitializationTime() const;
|
||||||
double getProcessingTime() const;
|
double getProcessingTime() const;
|
||||||
int getProcessedFrames() const;
|
unsigned getProcessedFrames() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void analysisFinished();
|
void analysisFinished();
|
||||||
|
|||||||
+22
-4
@@ -116,7 +116,15 @@ SOURCES += main.cpp\
|
|||||||
helpers/DPIHelper.cpp \
|
helpers/DPIHelper.cpp \
|
||||||
CustomStyle.cpp \
|
CustomStyle.cpp \
|
||||||
../AbstractAPOInfo.cpp \
|
../AbstractAPOInfo.cpp \
|
||||||
../VoicemeeterAPOInfo.cpp
|
../VoicemeeterAPOInfo.cpp \
|
||||||
|
../helpers/AbstractLibrary.cpp \
|
||||||
|
../helpers/VSTPluginLibrary.cpp \
|
||||||
|
guis/VSTPluginFilterGUI.cpp \
|
||||||
|
guis/VSTPluginFilterGUIFactory.cpp \
|
||||||
|
guis/VSTPluginFilterGUIDialog.cpp \
|
||||||
|
../filters/VSTPluginFilter.cpp \
|
||||||
|
../filters/VSTPluginFilterFactory.cpp \
|
||||||
|
../helpers/VSTPluginInstance.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
../helpers/LogHelper.h \
|
../helpers/LogHelper.h \
|
||||||
@@ -221,7 +229,15 @@ HEADERS += \
|
|||||||
helpers/DPIHelper.h \
|
helpers/DPIHelper.h \
|
||||||
CustomStyle.h \
|
CustomStyle.h \
|
||||||
../AbstractAPOInfo.h \
|
../AbstractAPOInfo.h \
|
||||||
../VoicemeeterAPOInfo.h
|
../VoicemeeterAPOInfo.h \
|
||||||
|
../helpers/AbstractLibrary.h \
|
||||||
|
../helpers/VSTPluginLibrary.h \
|
||||||
|
guis/VSTPluginFilterGUI.h \
|
||||||
|
guis/VSTPluginFilterGUIFactory.h \
|
||||||
|
guis/VSTPluginFilterGUIDialog.h \
|
||||||
|
../filters/VSTPluginFilter.h \
|
||||||
|
../filters/VSTPluginFilterFactory.h \
|
||||||
|
../helpers/VSTPluginInstance.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
guis/PreampFilterGUI.ui \
|
guis/PreampFilterGUI.ui \
|
||||||
@@ -239,10 +255,12 @@ FORMS += \
|
|||||||
guis/GraphicEQFilterGUI.ui \
|
guis/GraphicEQFilterGUI.ui \
|
||||||
guis/ConvolutionFilterGUI.ui \
|
guis/ConvolutionFilterGUI.ui \
|
||||||
MainWindow.ui \
|
MainWindow.ui \
|
||||||
guis/StageFilterGUI.ui
|
guis/StageFilterGUI.ui \
|
||||||
|
guis/VSTPluginFilterGUI.ui \
|
||||||
|
guis/VSTPluginFilterGUIDialog.ui
|
||||||
|
|
||||||
INCLUDEPATH += $$PWD/.. "C:/Program Files/libsndfile/include" "C:/Program Files/fftw3" "C:/Program Files/muparserx_v3_0_1/parser"
|
INCLUDEPATH += $$PWD/.. "C:/Program Files/libsndfile/include" "C:/Program Files/fftw3" "C:/Program Files/muparserx_v3_0_1/parser"
|
||||||
LIBS += user32.lib 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 crypt32.lib dbghelp.lib libsndfile-1.lib libfftw3f-3.lib
|
||||||
|
|
||||||
build_pass:CONFIG(debug, debug|release) {
|
build_pass:CONFIG(debug, debug|release) {
|
||||||
LIBS += muparserxd.lib
|
LIBS += muparserxd.lib
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
#include "guis/IncludeFilterGUIFactory.h"
|
#include "guis/IncludeFilterGUIFactory.h"
|
||||||
#include "guis/GraphicEQFilterGUIFactory.h"
|
#include "guis/GraphicEQFilterGUIFactory.h"
|
||||||
#include "guis/ConvolutionFilterGUIFactory.h"
|
#include "guis/ConvolutionFilterGUIFactory.h"
|
||||||
|
#include "guis/VSTPluginFilterGUIFactory.h"
|
||||||
#include "Editor/helpers/DPIHelper.h"
|
#include "Editor/helpers/DPIHelper.h"
|
||||||
#include "helpers/StringHelper.h"
|
#include "helpers/StringHelper.h"
|
||||||
#include "helpers/LogHelper.h"
|
#include "helpers/LogHelper.h"
|
||||||
@@ -79,10 +80,18 @@ FilterTable::FilterTable(MainWindow* mainWindow, QWidget* parent)
|
|||||||
factories.append(new CopyFilterGUIFactory);
|
factories.append(new CopyFilterGUIFactory);
|
||||||
factories.append(new GraphicEQFilterGUIFactory);
|
factories.append(new GraphicEQFilterGUIFactory);
|
||||||
factories.append(new ConvolutionFilterGUIFactory);
|
factories.append(new ConvolutionFilterGUIFactory);
|
||||||
|
factories.append(new VSTPluginFilterGUIFactory);
|
||||||
|
|
||||||
QApplication::instance()->installEventFilter(this);
|
QApplication::instance()->installEventFilter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FilterTable::~FilterTable()
|
||||||
|
{
|
||||||
|
for (IFilterGUIFactory* factory : factories)
|
||||||
|
delete factory;
|
||||||
|
factories.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void FilterTable::initialize(QScrollArea* scrollArea, const QList<shared_ptr<AbstractAPOInfo> >& outputDevices, const QList<shared_ptr<AbstractAPOInfo> >& inputDevices)
|
void FilterTable::initialize(QScrollArea* scrollArea, const QList<shared_ptr<AbstractAPOInfo> >& outputDevices, const QList<shared_ptr<AbstractAPOInfo> >& inputDevices)
|
||||||
{
|
{
|
||||||
this->scrollArea = scrollArea;
|
this->scrollArea = scrollArea;
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
explicit FilterTable(MainWindow* mainWindow, QWidget* parent = 0);
|
explicit FilterTable(MainWindow* mainWindow, QWidget* parent = 0);
|
||||||
|
~FilterTable();
|
||||||
void initialize(QScrollArea* scrollArea, const QList<std::shared_ptr<AbstractAPOInfo> >& outputDevices, const QList<std::shared_ptr<AbstractAPOInfo> >& inputDevices);
|
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 updateDeviceAndChannelMask(std::shared_ptr<AbstractAPOInfo> selectedDevice, int selectedChannelMask);
|
||||||
void updateGuis();
|
void updateGuis();
|
||||||
|
|||||||
+13
-1
@@ -427,6 +427,10 @@ void MainWindow::deviceSelected(int index)
|
|||||||
else
|
else
|
||||||
channelConfigurationComboBox->addItem(tr("From device") + " (" + apoInfo->getChannelCount() + " channels)", 0);
|
channelConfigurationComboBox->addItem(tr("From device") + " (" + apoInfo->getChannelCount() + " channels)", 0);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
channelConfigurationComboBox->addItem(tr("From device") + " (?)", 0);
|
||||||
|
}
|
||||||
|
|
||||||
for (const GUIChannelHelper::ChannelConfigurationInfo& info : infos)
|
for (const GUIChannelHelper::ChannelConfigurationInfo& info : infos)
|
||||||
channelConfigurationComboBox->addItem(info.name, info.channelMask);
|
channelConfigurationComboBox->addItem(info.name, info.channelMask);
|
||||||
@@ -469,6 +473,8 @@ void MainWindow::channelConfigurationSelected(int index)
|
|||||||
ui->analysisChannelComboBox->addItem(QString::fromStdWString(channelName));
|
ui->analysisChannelComboBox->addItem(QString::fromStdWString(channelName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startAnalysis();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::linesChanged()
|
void MainWindow::linesChanged()
|
||||||
@@ -723,6 +729,9 @@ void MainWindow::on_mainToolBar_visibilityChanged(bool visible)
|
|||||||
void MainWindow::on_analysisDockWidget_visibilityChanged(bool visible)
|
void MainWindow::on_analysisDockWidget_visibilityChanged(bool visible)
|
||||||
{
|
{
|
||||||
ui->actionAnalysisPanel->setChecked(visible);
|
ui->actionAnalysisPanel->setChecked(visible);
|
||||||
|
|
||||||
|
if (visible)
|
||||||
|
startAnalysis();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionToolbar_triggered(bool checked)
|
void MainWindow::on_actionToolbar_triggered(bool checked)
|
||||||
@@ -836,7 +845,7 @@ void MainWindow::getDeviceAndChannelMask(shared_ptr<AbstractAPOInfo>* selectedDe
|
|||||||
*selectedDevice = defaultOutputDevice;
|
*selectedDevice = defaultOutputDevice;
|
||||||
|
|
||||||
*channelMask = channelConfigurationComboBox->currentData().toInt();
|
*channelMask = channelConfigurationComboBox->currentData().toInt();
|
||||||
if (*channelMask == 0 && selectedDevice != NULL)
|
if (*channelMask == 0 && selectedDevice->get() != NULL)
|
||||||
{
|
{
|
||||||
*channelMask = (*selectedDevice)->getChannelMask();
|
*channelMask = (*selectedDevice)->getChannelMask();
|
||||||
|
|
||||||
@@ -894,6 +903,9 @@ bool MainWindow::askForClose(int tabIndex)
|
|||||||
|
|
||||||
void MainWindow::startAnalysis()
|
void MainWindow::startAnalysis()
|
||||||
{
|
{
|
||||||
|
if (!ui->analysisDockWidget->isVisible())
|
||||||
|
return;
|
||||||
|
|
||||||
shared_ptr<AbstractAPOInfo> selectedDevice;
|
shared_ptr<AbstractAPOInfo> selectedDevice;
|
||||||
|
|
||||||
int channelMask;
|
int channelMask;
|
||||||
|
|||||||
+1
-1
@@ -108,7 +108,7 @@ private:
|
|||||||
QList<std::shared_ptr<AbstractAPOInfo> > inputDevices;
|
QList<std::shared_ptr<AbstractAPOInfo> > inputDevices;
|
||||||
std::shared_ptr<AbstractAPOInfo> defaultOutputDevice;
|
std::shared_ptr<AbstractAPOInfo> defaultOutputDevice;
|
||||||
AnalysisPlotScene* analysisPlotScene;
|
AnalysisPlotScene* analysisPlotScene;
|
||||||
AnalysisThread* analysisThread;
|
AnalysisThread* analysisThread = NULL;
|
||||||
bool restart = false;
|
bool restart = false;
|
||||||
bool noSavePreferences = false;
|
bool noSavePreferences = false;
|
||||||
bool noSaveFilePreferences = false;
|
bool noSaveFilePreferences = false;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ QList<FilterTemplate> BiQuadFilterGUIFactory::createFilterTemplates()
|
|||||||
QList<FilterTemplate> list;
|
QList<FilterTemplate> list;
|
||||||
list.append(FilterTemplate(tr("Peaking filter"), "Filter: ON PK Fc 100 Hz Gain 0 dB Q 10", path));
|
list.append(FilterTemplate(tr("Peaking filter"), "Filter: ON PK Fc 100 Hz Gain 0 dB Q 10", path));
|
||||||
list.append(FilterTemplate(tr("Low-pass filter"), "Filter: ON LP Fc 100 Hz", path));
|
list.append(FilterTemplate(tr("Low-pass filter"), "Filter: ON LP Fc 100 Hz", path));
|
||||||
list.append(FilterTemplate(tr("High-pass filter"), "Filter: ON LP Fc 100 Hz", path));
|
list.append(FilterTemplate(tr("High-pass filter"), "Filter: ON HP Fc 100 Hz", path));
|
||||||
list.append(FilterTemplate(tr("Band-pass filter"), "Filter: ON BP Fc 100 Hz Q 10", path));
|
list.append(FilterTemplate(tr("Band-pass filter"), "Filter: ON BP Fc 100 Hz Q 10", path));
|
||||||
list.append(FilterTemplate(tr("Low-shelf filter"), "Filter: ON LS Fc 100 Hz Gain 0 dB", path));
|
list.append(FilterTemplate(tr("Low-shelf filter"), "Filter: ON LS Fc 100 Hz Gain 0 dB", path));
|
||||||
list.append(FilterTemplate(tr("High-shelf filter"), "Filter: ON HS Fc 100 Hz Gain 0 dB", path));
|
list.append(FilterTemplate(tr("High-shelf filter"), "Filter: ON HS Fc 100 Hz Gain 0 dB", path));
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>652</width>
|
<width>665</width>
|
||||||
<height>65</height>
|
<height>79</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@@ -58,7 +58,14 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="ResizingLineEdit" name="pathLineEdit"/>
|
<widget class="ResizingLineEdit" name="pathLineEdit">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="3">
|
<item row="0" column="3">
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
|||||||
@@ -175,8 +175,9 @@ void CopyFilterGUIConnectionItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent
|
|||||||
if (isDecibel)
|
if (isDecibel)
|
||||||
text += " dB";
|
text += " dB";
|
||||||
|
|
||||||
ResizingLineEdit* lineEdit = new ResizingLineEdit("");
|
ResizingLineEdit* lineEdit = new ResizingLineEdit(text, true);
|
||||||
connect(lineEdit, SIGNAL(editingFinished()), this, SLOT(lineEditEditingFinished()));
|
connect(lineEdit, SIGNAL(editingFinished()), this, SLOT(lineEditEditingFinished()));
|
||||||
|
connect(lineEdit, SIGNAL(editingCanceled()), this, SLOT(lineEditEditingCanceled()));
|
||||||
QGraphicsProxyWidget* proxyItem = scene()->addWidget(lineEdit);
|
QGraphicsProxyWidget* proxyItem = scene()->addWidget(lineEdit);
|
||||||
QLineF l = line();
|
QLineF l = line();
|
||||||
QPointF center = (l.p1() + l.p2()) / 2;
|
QPointF center = (l.p1() + l.p2()) / 2;
|
||||||
@@ -233,6 +234,14 @@ void CopyFilterGUIConnectionItem::lineEditEditingFinished()
|
|||||||
emit((CopyFilterGUIScene*)scene())->updateModel();
|
emit((CopyFilterGUIScene*)scene())->updateModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CopyFilterGUIConnectionItem::lineEditEditingCanceled()
|
||||||
|
{
|
||||||
|
QLineEdit* lineEdit = qobject_cast<QLineEdit*>(QObject::sender());
|
||||||
|
|
||||||
|
lineEdit->setVisible(false);
|
||||||
|
lineEdit->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
CopyFilterGUIChannelItem* CopyFilterGUIConnectionItem::getSource() const
|
CopyFilterGUIChannelItem* CopyFilterGUIConnectionItem::getSource() const
|
||||||
{
|
{
|
||||||
return source;
|
return source;
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ protected:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void lineEditEditingFinished();
|
void lineEditEditingFinished();
|
||||||
|
void lineEditEditingCanceled();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CopyFilterGUIChannelItem* source = NULL;
|
CopyFilterGUIChannelItem* source = NULL;
|
||||||
|
|||||||
@@ -162,8 +162,9 @@ std::vector<Assignment> CopyFilterGUIScene::buildAssignments()
|
|||||||
|
|
||||||
void CopyFilterGUIScene::addOutputChannel()
|
void CopyFilterGUIScene::addOutputChannel()
|
||||||
{
|
{
|
||||||
ResizingLineEdit* lineEdit = new ResizingLineEdit("");
|
ResizingLineEdit* lineEdit = new ResizingLineEdit("", true);
|
||||||
connect(lineEdit, SIGNAL(editingFinished()), this, SLOT(lineEditEditingFinished()));
|
connect(lineEdit, SIGNAL(editingFinished()), this, SLOT(lineEditEditingFinished()));
|
||||||
|
connect(lineEdit, SIGNAL(editingCanceled()), this, SLOT(lineEditEditingCanceled()));
|
||||||
QGraphicsProxyWidget* proxyItem = addWidget(lineEdit);
|
QGraphicsProxyWidget* proxyItem = addWidget(lineEdit);
|
||||||
QPointF point = getNextChannelPoint(lastOutputItem, true);
|
QPointF point = getNextChannelPoint(lastOutputItem, true);
|
||||||
QRectF rect;
|
QRectF rect;
|
||||||
@@ -183,13 +184,25 @@ void CopyFilterGUIScene::lineEditEditingFinished()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
QString text = lineEdit->text();
|
QString text = lineEdit->text();
|
||||||
|
if (text != "")
|
||||||
|
{
|
||||||
|
CopyFilterGUIChannelItem* item = new CopyFilterGUIChannelItem(text, true);
|
||||||
|
item->setPos(getNextChannelPoint(lastOutputItem, true));
|
||||||
|
addItem(item);
|
||||||
|
lastOutputItem = item;
|
||||||
|
|
||||||
CopyFilterGUIChannelItem* item = new CopyFilterGUIChannelItem(text, true);
|
addProxyItem->setPos(getNextChannelPoint(lastOutputItem, true));
|
||||||
item->setPos(getNextChannelPoint(lastOutputItem, true));
|
}
|
||||||
addItem(item);
|
addProxyItem->setVisible(true);
|
||||||
lastOutputItem = item;
|
|
||||||
|
lineEdit->setVisible(false);
|
||||||
|
lineEdit->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CopyFilterGUIScene::lineEditEditingCanceled()
|
||||||
|
{
|
||||||
|
QLineEdit* lineEdit = qobject_cast<QLineEdit*>(QObject::sender());
|
||||||
|
|
||||||
addProxyItem->setPos(getNextChannelPoint(lastOutputItem, true));
|
|
||||||
addProxyItem->setVisible(true);
|
addProxyItem->setVisible(true);
|
||||||
|
|
||||||
lineEdit->setVisible(false);
|
lineEdit->setVisible(false);
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ protected:
|
|||||||
private slots:
|
private slots:
|
||||||
void addOutputChannel();
|
void addOutputChannel();
|
||||||
void lineEditEditingFinished();
|
void lineEditEditingFinished();
|
||||||
|
void lineEditEditingCanceled();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QGraphicsItem* lastOutputItem;
|
QGraphicsItem* lastOutputItem;
|
||||||
|
|||||||
@@ -51,7 +51,14 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="ResizingLineEdit" name="pathLineEdit"/>
|
<widget class="ResizingLineEdit" name="pathLineEdit">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="0" column="2">
|
||||||
<widget class="QToolButton" name="selectFileToolButton">
|
<widget class="QToolButton" name="selectFileToolButton">
|
||||||
|
|||||||
@@ -0,0 +1,480 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 <QFileInfo>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QAbstractEventDispatcher>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include "helpers/aeffectx.h"
|
||||||
|
#include "helpers/StringHelper.h"
|
||||||
|
#include "Editor/helpers/DPIHelper.h"
|
||||||
|
#include "Editor/MainWindow.h"
|
||||||
|
#include "VSTPluginFilterGUIDialog.h"
|
||||||
|
#include "VSTPluginFilterGUI.h"
|
||||||
|
#include "ui_VSTPluginFilterGUI.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
VSTPluginFilterGUI::VSTPluginFilterGUI(std::shared_ptr<VSTPluginLibrary> library, const std::wstring& chunkData, const std::unordered_map<std::wstring, float>& paramMap)
|
||||||
|
: ui(new Ui::VSTPluginFilterGUI), library(library), chunkData(chunkData), paramMap(paramMap)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
ui->frame->setVisible(false);
|
||||||
|
updatePermissionWarning();
|
||||||
|
|
||||||
|
QString absolutePath = QString::fromStdWString(library->getLibPath());
|
||||||
|
QDir pluginsDir(QString::fromStdWString(VSTPluginLibrary::getDefaultPluginPath()));
|
||||||
|
QString relativePath = QDir::toNativeSeparators(pluginsDir.relativeFilePath(absolutePath));
|
||||||
|
if (relativePath.startsWith(QDir::toNativeSeparators("../../")))
|
||||||
|
relativePath = absolutePath;
|
||||||
|
ui->pathLineEdit->setText(relativePath);
|
||||||
|
|
||||||
|
QMenu* menu = new QMenu(ui->optionsButton);
|
||||||
|
menu->addAction(ui->embedAction);
|
||||||
|
ui->optionsButton->setMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
VSTPluginFilterGUI::~VSTPluginFilterGUI()
|
||||||
|
{
|
||||||
|
if (effect != NULL)
|
||||||
|
{
|
||||||
|
if (ui->embedAction->isChecked())
|
||||||
|
on_embedAction_toggled(false);
|
||||||
|
delete effect;
|
||||||
|
effect = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilterGUI::store(QString& command, QString& parameters)
|
||||||
|
{
|
||||||
|
command = "VSTPlugin";
|
||||||
|
|
||||||
|
QString absolutePath = QString::fromStdWString(library->getLibPath());
|
||||||
|
QDir pluginsDir(QString::fromStdWString(VSTPluginLibrary::getDefaultPluginPath()));
|
||||||
|
QString relativePath = QDir::toNativeSeparators(pluginsDir.relativeFilePath(absolutePath));
|
||||||
|
if (relativePath.startsWith(QDir::toNativeSeparators("../../")))
|
||||||
|
relativePath = absolutePath;
|
||||||
|
|
||||||
|
if (relativePath.contains(" "))
|
||||||
|
relativePath = "\"" + relativePath + "\"";
|
||||||
|
parameters = "Library " + relativePath;
|
||||||
|
|
||||||
|
if (chunkData != L"")
|
||||||
|
{
|
||||||
|
parameters += " ChunkData \"" + QString::fromStdWString(chunkData) + "\"";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto it : paramMap)
|
||||||
|
{
|
||||||
|
QString name = QString::fromStdWString(it.first);
|
||||||
|
if (name.contains(" ") || name.contains("\""))
|
||||||
|
name = "\"" + name.replace("\"", "\"\"") + "\"";
|
||||||
|
parameters += " " + name + " " + QString("%1").arg(it.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilterGUI::loadPreferences(const QVariantMap& prefs)
|
||||||
|
{
|
||||||
|
autoApplyDialog = prefs.value("autoApplyDialog").toBool();
|
||||||
|
|
||||||
|
if (prefs.value("embed").toBool())
|
||||||
|
// will also call initPlugin
|
||||||
|
ui->embedAction->setChecked(true);
|
||||||
|
else
|
||||||
|
initPlugin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilterGUI::storePreferences(QVariantMap& prefs)
|
||||||
|
{
|
||||||
|
prefs.insert("embed", ui->embedAction->isChecked());
|
||||||
|
prefs.insert("autoApplyDialog", autoApplyDialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilterGUI::on_openPanelButton_clicked()
|
||||||
|
{
|
||||||
|
initPlugin();
|
||||||
|
|
||||||
|
if (effect != NULL)
|
||||||
|
{
|
||||||
|
effect->writeToEffect(chunkData, paramMap);
|
||||||
|
|
||||||
|
VSTPluginFilterGUIDialog dialog(this, effect, autoApplyDialog);
|
||||||
|
connect(dialog.getApplyButton(), SIGNAL(pressed()), SLOT(applyDialog()));
|
||||||
|
connect(dialog.getAutoApplyCheckBox(), SIGNAL(toggled(bool)), SLOT(autoApplyToggled(bool)));
|
||||||
|
connect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), SLOT(on_idle()));
|
||||||
|
|
||||||
|
if (dialog.exec() == QDialog::Accepted)
|
||||||
|
{
|
||||||
|
effect->readFromEffect(chunkData, paramMap);
|
||||||
|
updateModel();
|
||||||
|
updatePermissionWarning();
|
||||||
|
}
|
||||||
|
disconnect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), this, SLOT(on_idle()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilterGUI::applyDialog()
|
||||||
|
{
|
||||||
|
effect->readFromEffect(chunkData, paramMap);
|
||||||
|
updateModel();
|
||||||
|
updatePermissionWarning();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilterGUI::autoApplyToggled(bool checked)
|
||||||
|
{
|
||||||
|
autoApplyDialog = checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilterGUI::initPlugin()
|
||||||
|
{
|
||||||
|
if (effect != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QColor color;
|
||||||
|
QString text;
|
||||||
|
if (library->getLibPath() == L"")
|
||||||
|
{
|
||||||
|
text = tr("No file selected.");
|
||||||
|
color = Qt::red;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int result = library->initialize();
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
color = Qt::red;
|
||||||
|
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case AbstractLibrary::FILE_NOT_FOUND:
|
||||||
|
text = tr("File not found.");
|
||||||
|
break;
|
||||||
|
case AbstractLibrary::LOADING_FAILED:
|
||||||
|
text = tr("Library could not be loaded.");
|
||||||
|
break;
|
||||||
|
case AbstractLibrary::FUNCTIONS_MISSING:
|
||||||
|
text = tr("Library does not contain needed functions.");
|
||||||
|
break;
|
||||||
|
case AbstractLibrary::WRONG_ARCHITECTURE:
|
||||||
|
#ifdef _WIN64
|
||||||
|
int bitDepth = 64;
|
||||||
|
#else
|
||||||
|
int bitDepth = 32;
|
||||||
|
#endif
|
||||||
|
text = tr("Library has the wrong architecture. Only %1-bit libraries are supported.").arg(bitDepth);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
effect = new VSTPluginInstance(library, 1);
|
||||||
|
if (effect->initialize())
|
||||||
|
{
|
||||||
|
effect->setLanguage(QLocale().language() == QLocale::German ? 2 : 1);
|
||||||
|
effect->setAutomateFunc(bind(&VSTPluginFilterGUI::onAutomate, this));
|
||||||
|
|
||||||
|
color = Qt::black;
|
||||||
|
text = QString::fromStdWString(effect->getName());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete effect;
|
||||||
|
effect = NULL;
|
||||||
|
|
||||||
|
color = Qt::red;
|
||||||
|
text = tr("Plugin crashed during initialization.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QPalette palette = ui->statusLabel->palette();
|
||||||
|
palette.setColor(QPalette::Active, QPalette::WindowText, color);
|
||||||
|
palette.setColor(QPalette::Inactive, QPalette::WindowText, color);
|
||||||
|
ui->statusLabel->setPalette(palette);
|
||||||
|
ui->statusLabel->setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilterGUI::on_pathLineEdit_editingFinished()
|
||||||
|
{
|
||||||
|
if (QString::fromStdWString(library->getLibPath()) != ui->pathLineEdit->text())
|
||||||
|
{
|
||||||
|
int oldId = 0;
|
||||||
|
if (effect != NULL)
|
||||||
|
{
|
||||||
|
oldId = effect->uniqueID();
|
||||||
|
if (ui->embedAction->isChecked())
|
||||||
|
on_embedAction_toggled(false);
|
||||||
|
delete effect;
|
||||||
|
effect = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDir pluginsDir(QString::fromStdWString(VSTPluginLibrary::getDefaultPluginPath()));
|
||||||
|
QString path = ui->pathLineEdit->text();
|
||||||
|
if (path.length() > 0)
|
||||||
|
path = QDir::toNativeSeparators(QFileInfo(pluginsDir, ui->pathLineEdit->text()).absoluteFilePath());
|
||||||
|
library = VSTPluginLibrary::getInstance(path.toStdWString());
|
||||||
|
initPlugin();
|
||||||
|
|
||||||
|
if (effect == NULL || oldId == 0 || effect->uniqueID() != oldId)
|
||||||
|
{
|
||||||
|
chunkData = L"";
|
||||||
|
paramMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateModel();
|
||||||
|
updatePermissionWarning();
|
||||||
|
|
||||||
|
if (ui->embedAction->isChecked())
|
||||||
|
on_embedAction_toggled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilterGUI::on_selectButton_clicked()
|
||||||
|
{
|
||||||
|
QDir pluginsDir(QString::fromStdWString(VSTPluginLibrary::getDefaultPluginPath()));
|
||||||
|
|
||||||
|
QSettings settings(QString::fromWCharArray(EDITOR_REGPATH), QSettings::NativeFormat);
|
||||||
|
QString lastDir = settings.value("vst/lastDir", "").toString();
|
||||||
|
if (lastDir == "")
|
||||||
|
lastDir = pluginsDir.absolutePath();
|
||||||
|
|
||||||
|
QFileInfo fileInfo(lastDir);
|
||||||
|
QString path = ui->pathLineEdit->text();
|
||||||
|
if (path.length() > 0)
|
||||||
|
fileInfo.setFile(pluginsDir, path);
|
||||||
|
|
||||||
|
QFileDialog dialog(this, tr("Select VST plugin"), fileInfo.absoluteFilePath(), "*.dll");
|
||||||
|
dialog.setFileMode(QFileDialog::ExistingFile);
|
||||||
|
dialog.setNameFilter(tr("VST plugins (*.dll)"));
|
||||||
|
if (path.length() > 0)
|
||||||
|
dialog.selectFile(fileInfo.fileName());
|
||||||
|
if (dialog.exec() == QDialog::Accepted)
|
||||||
|
{
|
||||||
|
QString absolutePath = dialog.selectedFiles().first();
|
||||||
|
settings.setValue("vst/lastDir", QDir::toNativeSeparators(QFileInfo(absolutePath).absolutePath()));
|
||||||
|
QString relativePath = pluginsDir.relativeFilePath(absolutePath);
|
||||||
|
if (relativePath.startsWith("../../"))
|
||||||
|
relativePath = absolutePath;
|
||||||
|
ui->pathLineEdit->setText(QDir::toNativeSeparators(relativePath));
|
||||||
|
on_pathLineEdit_editingFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilterGUI::on_embedAction_toggled(bool checked)
|
||||||
|
{
|
||||||
|
initPlugin();
|
||||||
|
|
||||||
|
ui->openPanelButton->setVisible(!checked);
|
||||||
|
|
||||||
|
bool enable = checked;
|
||||||
|
if (effect == NULL)
|
||||||
|
enable = false;
|
||||||
|
|
||||||
|
bool wasEnabled = ui->frame->isVisible();
|
||||||
|
if (enable != wasEnabled)
|
||||||
|
{
|
||||||
|
ui->frame->setVisible(enable);
|
||||||
|
ui->statusLabel->setVisible(!enable);
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
if (embedPlugin())
|
||||||
|
{
|
||||||
|
effect->setSizeWindowFunc(bind(&VSTPluginFilterGUI::onSizeWindow, this, _1, _2));
|
||||||
|
connect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), SLOT(on_idle()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui->frame->setVisible(false);
|
||||||
|
ui->statusLabel->setVisible(true);
|
||||||
|
|
||||||
|
QPalette palette = ui->statusLabel->palette();
|
||||||
|
palette.setColor(QPalette::Active, QPalette::WindowText, Qt::red);
|
||||||
|
palette.setColor(QPalette::Inactive, QPalette::WindowText, Qt::red);
|
||||||
|
ui->statusLabel->setPalette(palette);
|
||||||
|
ui->statusLabel->setText(tr("Plugin crashed when opening panel."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (effect != NULL)
|
||||||
|
{
|
||||||
|
effect->stopEditing();
|
||||||
|
effect->setSizeWindowFunc(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), this, SLOT(on_idle()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilterGUI::on_idle()
|
||||||
|
{
|
||||||
|
if (effect != NULL)
|
||||||
|
{
|
||||||
|
effect->doIdle();
|
||||||
|
|
||||||
|
if (ui->frame->isVisible() || autoApplyDialog)
|
||||||
|
{
|
||||||
|
if (!lastReadTimer.isValid() || lastReadTimer.elapsed() > 1000)
|
||||||
|
{
|
||||||
|
wstring newChunkData;
|
||||||
|
unordered_map<std::wstring, float> newParamMap;
|
||||||
|
effect->readFromEffect(newChunkData, newParamMap);
|
||||||
|
if (newChunkData != chunkData || newParamMap != paramMap)
|
||||||
|
{
|
||||||
|
chunkData = newChunkData;
|
||||||
|
paramMap = newParamMap;
|
||||||
|
updateModel();
|
||||||
|
updatePermissionWarning();
|
||||||
|
}
|
||||||
|
lastReadTimer.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilterGUI::onAutomate()
|
||||||
|
{
|
||||||
|
if (ui->frame->isVisible() || autoApplyDialog)
|
||||||
|
{
|
||||||
|
effect->readFromEffect(chunkData, paramMap);
|
||||||
|
updateModel();
|
||||||
|
updatePermissionWarning();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilterGUI::onSizeWindow(int w, int h)
|
||||||
|
{
|
||||||
|
if (ui->frame->isVisible())
|
||||||
|
ui->frame->setFixedSize(w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VSTPluginFilterGUI::embedPlugin()
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
effect->writeToEffect(chunkData, paramMap);
|
||||||
|
|
||||||
|
HWND hwnd = (HWND)ui->frame->winId();
|
||||||
|
short width, height;
|
||||||
|
|
||||||
|
effect->startEditing(hwnd, &width, &height);
|
||||||
|
|
||||||
|
ui->frame->setFixedSize(width, height);
|
||||||
|
}
|
||||||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilterGUI::updatePermissionWarning()
|
||||||
|
{
|
||||||
|
if (effect == NULL)
|
||||||
|
{
|
||||||
|
ui->warningTextEdit->setVisible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ACCESS_MASK mask = GENERIC_READ;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mask = RegistryHelper::getFileAccessForUser(library->getLibPath(), SECURITY_LOCAL_SERVICE_RID);
|
||||||
|
}
|
||||||
|
catch (RegistryException e)
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mask & GENERIC_READ) != GENERIC_READ && (mask & FILE_GENERIC_READ) != FILE_GENERIC_READ)
|
||||||
|
{
|
||||||
|
QString text = tr("The library is not readable by the audio service.\nChange the file permissions or copy the file to the plugins directory.");
|
||||||
|
|
||||||
|
ui->warningTextEdit->setPlainText(text);
|
||||||
|
QSize textSize = ui->warningTextEdit->fontMetrics().size(0, text);
|
||||||
|
ui->warningTextEdit->setFixedSize(textSize + DPIHelper::scale(QSize(40, 15)));
|
||||||
|
ui->warningTextEdit->setVisible(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList files;
|
||||||
|
if (chunkData != L"" && chunkData.length() < 100000)
|
||||||
|
{
|
||||||
|
QByteArray bytes = QByteArray::fromBase64(QString::fromStdWString(chunkData).toUtf8());
|
||||||
|
QString string = QString::fromUtf8(bytes.data(), bytes.length());
|
||||||
|
QRegExp regexp("[A-Za-z]:(?:\\\\[\\w \\(\\)-]+)+\\.[A-Za-z]{3}");
|
||||||
|
int offset = 0;
|
||||||
|
while (offset >= 0)
|
||||||
|
{
|
||||||
|
offset = regexp.indexIn(string, offset);
|
||||||
|
if (offset >= 0)
|
||||||
|
{
|
||||||
|
QString path = regexp.cap();
|
||||||
|
QFile file(path);
|
||||||
|
if (file.exists())
|
||||||
|
{
|
||||||
|
ACCESS_MASK mask = GENERIC_READ;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mask = RegistryHelper::getFileAccessForUser(path.toStdWString(), SECURITY_LOCAL_SERVICE_RID);
|
||||||
|
}
|
||||||
|
catch (RegistryException e)
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mask & GENERIC_READ) != GENERIC_READ && (mask & FILE_GENERIC_READ) != FILE_GENERIC_READ)
|
||||||
|
files.append(path);
|
||||||
|
}
|
||||||
|
offset += regexp.matchedLength();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (files.isEmpty())
|
||||||
|
{
|
||||||
|
ui->warningTextEdit->setVisible(false);
|
||||||
|
ui->warningTextEdit->setPlainText("");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
files.removeDuplicates();
|
||||||
|
QString text = tr("The plugin seemingly accesses these files not readable by the audio service:\n"
|
||||||
|
"%0\n"
|
||||||
|
"Change the file permissions or copy the files to the config directory.").arg(files.join("\n"));
|
||||||
|
ui->warningTextEdit->setPlainText(text);
|
||||||
|
QSize textSize = ui->warningTextEdit->fontMetrics().size(0, text);
|
||||||
|
ui->warningTextEdit->setFixedSize(textSize + DPIHelper::scale(QSize(40, 15)));
|
||||||
|
ui->warningTextEdit->setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 <memory>
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
#include "Editor/IFilterGUI.h"
|
||||||
|
#include "helpers/VSTPluginLibrary.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class VSTPluginFilterGUI;
|
||||||
|
}
|
||||||
|
|
||||||
|
class VSTPluginFilterGUI : public IFilterGUI
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit VSTPluginFilterGUI(std::shared_ptr<VSTPluginLibrary> library, const std::wstring& chunkData, const std::unordered_map<std::wstring, float>& paramMap);
|
||||||
|
~VSTPluginFilterGUI();
|
||||||
|
|
||||||
|
void store(QString& command, QString& parameters) override;
|
||||||
|
void loadPreferences(const QVariantMap& prefs) override;
|
||||||
|
void storePreferences(QVariantMap& prefs) override;
|
||||||
|
void onAutomate();
|
||||||
|
void onSizeWindow(int w, int h);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_openPanelButton_clicked();
|
||||||
|
void applyDialog();
|
||||||
|
void autoApplyToggled(bool checked);
|
||||||
|
void on_pathLineEdit_editingFinished();
|
||||||
|
void on_selectButton_clicked();
|
||||||
|
void on_embedAction_toggled(bool checked);
|
||||||
|
void on_idle();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initPlugin();
|
||||||
|
bool embedPlugin();
|
||||||
|
void updatePermissionWarning();
|
||||||
|
|
||||||
|
Ui::VSTPluginFilterGUI* ui;
|
||||||
|
std::shared_ptr<VSTPluginLibrary> library;
|
||||||
|
VSTPluginInstance* effect = NULL;
|
||||||
|
std::wstring chunkData;
|
||||||
|
std::unordered_map<std::wstring, float> paramMap;
|
||||||
|
bool autoApplyDialog = false;
|
||||||
|
QElapsedTimer lastReadTimer;
|
||||||
|
};
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>VSTPluginFilterGUI</class>
|
||||||
|
<widget class="QWidget" name="VSTPluginFilterGUI">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>542</width>
|
||||||
|
<height>166</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_3" columnstretch="0,0,0,0,1">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="verticalSpacing">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="ResizingLineEdit" name="pathLineEdit"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2" colspan="2">
|
||||||
|
<widget class="QPushButton" name="openPanelButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Open panel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>VST plugin:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="statusLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="4">
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QToolButton" name="optionsButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Options</string>
|
||||||
|
</property>
|
||||||
|
<property name="popupMode">
|
||||||
|
<enum>QToolButton::MenuButtonPopup</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolButtonStyle">
|
||||||
|
<enum>Qt::ToolButtonTextOnly</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QToolButton" name="selectButton">
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../Editor.qrc">
|
||||||
|
<normaloff>:/icons/document-open.ico</normaloff>:/icons/document-open.ico</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" colspan="4">
|
||||||
|
<widget class="QFrame" name="frame">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0" colspan="4">
|
||||||
|
<widget class="QPlainTextEdit" name="warningTextEdit">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="palette">
|
||||||
|
<palette>
|
||||||
|
<active>
|
||||||
|
<colorrole role="Base">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>255</green>
|
||||||
|
<blue>127</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</active>
|
||||||
|
<inactive>
|
||||||
|
<colorrole role="Base">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>255</green>
|
||||||
|
<blue>127</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</inactive>
|
||||||
|
<disabled>
|
||||||
|
<colorrole role="Base">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>240</red>
|
||||||
|
<green>240</green>
|
||||||
|
<blue>240</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</disabled>
|
||||||
|
</palette>
|
||||||
|
</property>
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
<action name="embedAction">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Embed</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>ResizingLineEdit</class>
|
||||||
|
<extends>QLineEdit</extends>
|
||||||
|
<header>Editor/widgets/ResizingLineEdit.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources>
|
||||||
|
<include location="../Editor.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>optionsButton</sender>
|
||||||
|
<signal>clicked()</signal>
|
||||||
|
<receiver>optionsButton</receiver>
|
||||||
|
<slot>showMenu()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>288</x>
|
||||||
|
<y>12</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>288</x>
|
||||||
|
<y>12</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 <QPushButton>
|
||||||
|
#include "VSTPluginFilterGUIDialog.h"
|
||||||
|
#include "ui_VSTPluginFilterGUIDialog.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
VSTPluginFilterGUIDialog::VSTPluginFilterGUIDialog(QWidget* parent, VSTPluginInstance* effect, bool autoApply)
|
||||||
|
: QDialog(parent, Qt::WindowCloseButtonHint),
|
||||||
|
ui(new Ui::VSTPluginFilterGUIDialog),
|
||||||
|
effect(effect)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
ui->autoApplyCheckBox->setChecked(autoApply);
|
||||||
|
|
||||||
|
QString name = QString::fromStdWString(effect->getName());
|
||||||
|
setWindowTitle(name);
|
||||||
|
|
||||||
|
HWND hwnd = (HWND)ui->frame->winId();
|
||||||
|
|
||||||
|
short width, height;
|
||||||
|
|
||||||
|
effect->startEditing(hwnd, &width, &height);
|
||||||
|
|
||||||
|
ui->frame->setFixedSize(width, height);
|
||||||
|
effect->setSizeWindowFunc(bind(&VSTPluginFilterGUIDialog::onSizeWindow, this, _1, _2));
|
||||||
|
}
|
||||||
|
|
||||||
|
VSTPluginFilterGUIDialog::~VSTPluginFilterGUIDialog()
|
||||||
|
{
|
||||||
|
effect->stopEditing();
|
||||||
|
effect->setSizeWindowFunc(nullptr);
|
||||||
|
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton* VSTPluginFilterGUIDialog::getApplyButton()
|
||||||
|
{
|
||||||
|
return ui->buttonBox->button(QDialogButtonBox::Apply);
|
||||||
|
}
|
||||||
|
|
||||||
|
QCheckBox* VSTPluginFilterGUIDialog::getAutoApplyCheckBox()
|
||||||
|
{
|
||||||
|
return ui->autoApplyCheckBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilterGUIDialog::onSizeWindow(int w, int h)
|
||||||
|
{
|
||||||
|
ui->frame->setFixedSize(w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilterGUIDialog::on_autoApplyCheckBox_clicked(bool checked)
|
||||||
|
{
|
||||||
|
if (checked)
|
||||||
|
getApplyButton()->click();
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 <QDialog>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include "helpers/VSTPluginInstance.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class VSTPluginFilterGUIDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class VSTPluginFilterGUIDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit VSTPluginFilterGUIDialog(QWidget* parent, VSTPluginInstance* effect, bool autoApply);
|
||||||
|
~VSTPluginFilterGUIDialog();
|
||||||
|
|
||||||
|
QPushButton* getApplyButton();
|
||||||
|
QCheckBox* getAutoApplyCheckBox();
|
||||||
|
|
||||||
|
void onSizeWindow(int w, int h);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_autoApplyCheckBox_clicked(bool checked);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::VSTPluginFilterGUIDialog* ui;
|
||||||
|
VSTPluginInstance* effect;
|
||||||
|
};
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>VSTPluginFilterGUIDialog</class>
|
||||||
|
<widget class="QDialog" name="VSTPluginFilterGUIDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>459</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QCheckBox" name="autoApplyCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Apply automatically</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" colspan="2">
|
||||||
|
<widget class="QFrame" name="frame">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>VSTPluginFilterGUIDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>VSTPluginFilterGUIDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 "helpers/VSTPluginLibrary.h"
|
||||||
|
#include "helpers/StringHelper.h"
|
||||||
|
#include "filters/VSTPluginFilterFactory.h"
|
||||||
|
#include "filters/VSTPluginFilter.h"
|
||||||
|
#include "VSTPluginFilterGUI.h"
|
||||||
|
#include "VSTPluginFilterGUIFactory.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
QList<FilterTemplate> VSTPluginFilterGUIFactory::createFilterTemplates()
|
||||||
|
{
|
||||||
|
QList<FilterTemplate> list;
|
||||||
|
list.append(FilterTemplate(tr("VST plugin"), "VSTPlugin:", QStringList(tr("Plugins"))));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
IFilterGUI* VSTPluginFilterGUIFactory::createFilterGUI(QString& command, QString& parameters)
|
||||||
|
{
|
||||||
|
VSTPluginFilterGUI* result = NULL;
|
||||||
|
|
||||||
|
if (command == "VSTPlugin")
|
||||||
|
{
|
||||||
|
VSTPluginFilterFactory factory;
|
||||||
|
std::vector<IFilter*> filters = factory.createFilter(L"", command.toStdWString(), parameters.toStdWString());
|
||||||
|
if (!filters.empty())
|
||||||
|
{
|
||||||
|
VSTPluginFilter* filter = (VSTPluginFilter*)filters[0];
|
||||||
|
result = new VSTPluginFilterGUI(filter->getLibrary(), filter->getChunkData(), filter->getParamMap());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = new VSTPluginFilterGUI(VSTPluginLibrary::getInstance(L""), L"", unordered_map<wstring, float>());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (IFilter* f : filters)
|
||||||
|
{
|
||||||
|
f->~IFilter();
|
||||||
|
MemoryHelper::free(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 "Editor/IFilterGUIFactory.h"
|
||||||
|
|
||||||
|
class VSTPluginFilterGUIFactory : public IFilterGUIFactory
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
QList<FilterTemplate> createFilterTemplates() override;
|
||||||
|
IFilterGUI* createFilterGUI(QString& command, QString& parameters) override;
|
||||||
|
};
|
||||||
Binary file not shown.
@@ -281,24 +281,24 @@
|
|||||||
<translation>Faltung mit Impulsantwort:</translation>
|
<translation>Faltung mit Impulsantwort:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../guis/ConvolutionFilterGUI.ui" line="66"/>
|
<location filename="../guis/ConvolutionFilterGUI.ui" line="73"/>
|
||||||
<source>File information</source>
|
<source>File information</source>
|
||||||
<translation>Dateiinformationen</translation>
|
<translation>Dateiinformationen</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../guis/ConvolutionFilterGUI.ui" line="72"/>
|
<location filename="../guis/ConvolutionFilterGUI.ui" line="79"/>
|
||||||
<source>Sample rate:</source>
|
<source>Sample rate:</source>
|
||||||
<translation>Abtastrate:</translation>
|
<translation>Abtastrate:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../guis/ConvolutionFilterGUI.ui" line="79"/>
|
<location filename="../guis/ConvolutionFilterGUI.ui" line="86"/>
|
||||||
<location filename="../guis/ConvolutionFilterGUI.ui" line="137"/>
|
<location filename="../guis/ConvolutionFilterGUI.ui" line="144"/>
|
||||||
<location filename="../guis/ConvolutionFilterGUI.cpp" line="91"/>
|
<location filename="../guis/ConvolutionFilterGUI.cpp" line="91"/>
|
||||||
<source>No file selected</source>
|
<source>No file selected</source>
|
||||||
<translation>Keine Datei gewählt</translation>
|
<translation>Keine Datei gewählt</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../guis/ConvolutionFilterGUI.ui" line="130"/>
|
<location filename="../guis/ConvolutionFilterGUI.ui" line="137"/>
|
||||||
<source>Length:</source>
|
<source>Length:</source>
|
||||||
<translation>Länge:</translation>
|
<translation>Länge:</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -661,7 +661,7 @@ Wählen Sie eine andere Datei oder ändern Sie die Konfiguration des Geräts.</t
|
|||||||
<context>
|
<context>
|
||||||
<name>FilterTable</name>
|
<name>FilterTable</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../FilterTable.cpp" line="205"/>
|
<location filename="../FilterTable.cpp" line="214"/>
|
||||||
<source>Add filter</source>
|
<source>Add filter</source>
|
||||||
<translation>Filter hinzufügen</translation>
|
<translation>Filter hinzufügen</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -838,12 +838,12 @@ Wählen Sie eine andere Datei oder ändern Sie die Konfiguration des Geräts.</t
|
|||||||
<context>
|
<context>
|
||||||
<name>IncludeFilterGUI</name>
|
<name>IncludeFilterGUI</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../guis/IncludeFilterGUI.ui" line="70"/>
|
<location filename="../guis/IncludeFilterGUI.ui" line="77"/>
|
||||||
<source>Include:</source>
|
<source>Include:</source>
|
||||||
<translation>Einbinden:</translation>
|
<translation>Einbinden:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../guis/IncludeFilterGUI.ui" line="59"/>
|
<location filename="../guis/IncludeFilterGUI.ui" line="66"/>
|
||||||
<source>Select file</source>
|
<source>Select file</source>
|
||||||
<translation>Datei auswählen</translation>
|
<translation>Datei auswählen</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1198,11 +1198,12 @@ Möchten Sie die Configurator-Anwendung starten, um das Problem zu beheben?</tra
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../MainWindow.cpp" line="426"/>
|
<location filename="../MainWindow.cpp" line="426"/>
|
||||||
<location filename="../MainWindow.cpp" line="428"/>
|
<location filename="../MainWindow.cpp" line="428"/>
|
||||||
|
<location filename="../MainWindow.cpp" line="432"/>
|
||||||
<source>From device</source>
|
<source>From device</source>
|
||||||
<translation>Von Gerät</translation>
|
<translation>Von Gerät</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../MainWindow.cpp" line="704"/>
|
<location filename="../MainWindow.cpp" line="710"/>
|
||||||
<source>%0 dB</source>
|
<source>%0 dB</source>
|
||||||
<translation>%0 dB</translation>
|
<translation>%0 dB</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1211,7 +1212,7 @@ Möchten Sie die Configurator-Anwendung starten, um das Problem zu beheben?</tra
|
|||||||
<translation type="vanished">%0 ms (%1 Samp.)</translation>
|
<translation type="vanished">%0 ms (%1 Samp.)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../MainWindow.cpp" line="707"/>
|
<location filename="../MainWindow.cpp" line="713"/>
|
||||||
<source>%0 ms (%1 s.)</source>
|
<source>%0 ms (%1 s.)</source>
|
||||||
<translation>%0 ms (%1 S.)</translation>
|
<translation>%0 ms (%1 S.)</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1220,46 +1221,46 @@ Möchten Sie die Configurator-Anwendung starten, um das Problem zu beheben?</tra
|
|||||||
<translation type="vanished">%0 ms (%1 Samples)</translation>
|
<translation type="vanished">%0 ms (%1 Samples)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../MainWindow.cpp" line="709"/>
|
<location filename="../MainWindow.cpp" line="715"/>
|
||||||
<source>%0 ms</source>
|
<source>%0 ms</source>
|
||||||
<translation>%0 ms</translation>
|
<translation>%0 ms</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../MainWindow.cpp" line="712"/>
|
<location filename="../MainWindow.cpp" line="718"/>
|
||||||
<source>%0 % (one core)</source>
|
<source>%0 % (one core)</source>
|
||||||
<translation>%0 % (ein Kern)</translation>
|
<translation>%0 % (ein Kern)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../MainWindow.cpp" line="750"/>
|
<location filename="../MainWindow.cpp" line="759"/>
|
||||||
<location filename="../MainWindow.cpp" line="777"/>
|
<location filename="../MainWindow.cpp" line="786"/>
|
||||||
<location filename="../MainWindow.cpp" line="796"/>
|
<location filename="../MainWindow.cpp" line="805"/>
|
||||||
<source>Restart required</source>
|
<source>Restart required</source>
|
||||||
<translation>Neustart erforderlich</translation>
|
<translation>Neustart erforderlich</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../MainWindow.cpp" line="750"/>
|
<location filename="../MainWindow.cpp" line="759"/>
|
||||||
<location filename="../MainWindow.cpp" line="777"/>
|
<location filename="../MainWindow.cpp" line="786"/>
|
||||||
<location filename="../MainWindow.cpp" line="796"/>
|
<location filename="../MainWindow.cpp" line="805"/>
|
||||||
<source>Configuration Editor will be restarted to apply the changed settings. Proceed?</source>
|
<source>Configuration Editor will be restarted to apply the changed settings. Proceed?</source>
|
||||||
<translation>Konfigurationseditor wird neugestartet, um die geänderten Einstellungen zu übernehmen. Fortsetzen?</translation>
|
<translation>Konfigurationseditor wird neugestartet, um die geänderten Einstellungen zu übernehmen. Fortsetzen?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../MainWindow.cpp" line="856"/>
|
<location filename="../MainWindow.cpp" line="865"/>
|
||||||
<source>Unsaved changes</source>
|
<source>Unsaved changes</source>
|
||||||
<translation>Ungespeicherte Änderungen</translation>
|
<translation>Ungespeicherte Änderungen</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../MainWindow.cpp" line="857"/>
|
<location filename="../MainWindow.cpp" line="866"/>
|
||||||
<source>The configuration file %0 has unsaved changes.</source>
|
<source>The configuration file %0 has unsaved changes.</source>
|
||||||
<translation>Die Konfigurationsdatei %0 hat ungespeicherte Änderungen.</translation>
|
<translation>Die Konfigurationsdatei %0 hat ungespeicherte Änderungen.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../MainWindow.cpp" line="858"/>
|
<location filename="../MainWindow.cpp" line="867"/>
|
||||||
<source>Do you want to save the changes before closing the file?</source>
|
<source>Do you want to save the changes before closing the file?</source>
|
||||||
<translation>Möchten Sie die Änderungen speichern, bevor die Datei geschlossen wird?</translation>
|
<translation>Möchten Sie die Änderungen speichern, bevor die Datei geschlossen wird?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../MainWindow.cpp" line="529"/>
|
<location filename="../MainWindow.cpp" line="535"/>
|
||||||
<source>Open file</source>
|
<source>Open file</source>
|
||||||
<translation>Datei öffnen</translation>
|
<translation>Datei öffnen</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1269,22 +1270,110 @@ Möchten Sie die Configurator-Anwendung starten, um das Problem zu beheben?</tra
|
|||||||
<translation>Automatisch (%0)</translation>
|
<translation>Automatisch (%0)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../MainWindow.cpp" line="531"/>
|
<location filename="../MainWindow.cpp" line="537"/>
|
||||||
<location filename="../MainWindow.cpp" line="584"/>
|
<location filename="../MainWindow.cpp" line="590"/>
|
||||||
<source>E-APO configurations (*.txt)</source>
|
<source>E-APO configurations (*.txt)</source>
|
||||||
<translation>E-APO-Konfigurationen (*.txt)</translation>
|
<translation>E-APO-Konfigurationen (*.txt)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../MainWindow.cpp" line="581"/>
|
<location filename="../MainWindow.cpp" line="587"/>
|
||||||
<source>Save file as</source>
|
<source>Save file as</source>
|
||||||
<translation>Datei speichern unter</translation>
|
<translation>Datei speichern unter</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../MainWindow.cpp" line="603"/>
|
<location filename="../MainWindow.cpp" line="609"/>
|
||||||
<source>Unsaved</source>
|
<source>Unsaved</source>
|
||||||
<translation>Ungespeichert</translation>
|
<translation>Ungespeichert</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MathAudioFilterGUI</name>
|
||||||
|
<message>
|
||||||
|
<source>Open panel</source>
|
||||||
|
<translation type="vanished">Panel öffnen</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Status information</source>
|
||||||
|
<translation type="vanished">Statusinformationen</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>File %1 not found.</source>
|
||||||
|
<translation type="vanished">Datei %1 nicht gefunden.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Library %1 could not be loaded.</source>
|
||||||
|
<translation type="vanished">Bibliothek %1 konnte nicht geladen werden.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Library %1 does not contain needed functions.</source>
|
||||||
|
<translation type="vanished">Bibliothek %1 enthält nicht die benötigten Funktionen.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Library %1 could not be initialized.</source>
|
||||||
|
<translation type="vanished">Bibliothek %1 konnte nicht initialisiert werden.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Get library from <a href="%1">download page</a> and<br>extract %2-bit version of %3 into <a href="%4">plugins</a> directory.</source>
|
||||||
|
<translation type="vanished">Bibliothek von der <a href="%1">Downloadseite</a> laden und<br>die %2-bit-Version von %3 in das Verzeichnis <a href="%4">plugins</a> extrahieren.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Library loaded successfully. Version: %1</source>
|
||||||
|
<translation type="vanished">Bibliothek erfolgreich geladen. Version: %1</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>For updates, get new version from <a href="%1">download page</a>, close Configuration Editor and<br>extract %2-bit version of %3 into <a href="%4">plugins</a> directory.</source>
|
||||||
|
<translation type="vanished">Für Updates, neue Version von der <a href="%1">Downloadseite</a> laden, den Konfigurationseditor schließen und<br>die %2-bit-Version von %3 in das Verzeichnis <a href="%4">plugins</a> extrahieren.</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MathAudioFilterGUIFactory</name>
|
||||||
|
<message>
|
||||||
|
<source>Plugins</source>
|
||||||
|
<translation type="vanished">Plugins</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MathAudioHeadphoneEQFilterGUI</name>
|
||||||
|
<message>
|
||||||
|
<source>Open panel</source>
|
||||||
|
<translation type="vanished">Panel öffnen</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Status information</source>
|
||||||
|
<translation type="vanished">Statusinformationen</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>File %1 not found.</source>
|
||||||
|
<translation type="vanished">Datei %1 nicht gefunden.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Library %1 could not be loaded.</source>
|
||||||
|
<translation type="vanished">Bibliothek %1 konnte nicht geladen werden.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Library %1 does not contain needed functions.</source>
|
||||||
|
<translation type="vanished">Bibliothek %1 enthält nicht die benötigten Funktionen.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Get library from <a href="%1">download page</a> and<br>extract %2-bit version of %3 into <a href="%4">plugins</a> directory.</source>
|
||||||
|
<translation type="vanished">Bibliothek von der <a href="%1">Downloadseite</a> laden und<br>die %2-bit-Version von %3 in das Verzeichnis <a href="%4">plugins</a> extrahieren.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Library loaded successfully.</source>
|
||||||
|
<translation type="vanished">Bibliothek erfolgreich geladen.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>For updates, get new version from <a href="%1">download page</a>, close Configuration Editor and<br>extract %2-bit version of %3 into <a href="%4">plugins</a> directory.</source>
|
||||||
|
<translation type="vanished">Für Updates, neue Version von der <a href="%1">Downloadseite</a> laden, den Konfigurationseditor schließen und<br>die %2-bit-Version von %3 in das Verzeichnis <a href="%4">plugins</a> extrahieren.</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MathAudioHeadphoneEQFilterGUIFactory</name>
|
||||||
|
<message>
|
||||||
|
<source>Plugins</source>
|
||||||
|
<translation type="vanished">Plugins</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PreampFilterGUI</name>
|
<name>PreampFilterGUI</name>
|
||||||
<message>
|
<message>
|
||||||
@@ -1374,4 +1463,113 @@ Möchten Sie die Configurator-Anwendung starten, um das Problem zu beheben?</tra
|
|||||||
<translation>Steuerung</translation>
|
<translation>Steuerung</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>VSTPluginFilterGUI</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUI.ui" line="84"/>
|
||||||
|
<source>Options</source>
|
||||||
|
<translation>Optionen</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUI.ui" line="44"/>
|
||||||
|
<source>Open panel</source>
|
||||||
|
<translation>Panel öffnen</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUI.ui" line="57"/>
|
||||||
|
<source>VST plugin:</source>
|
||||||
|
<translation>VST-Plugin:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUI.ui" line="171"/>
|
||||||
|
<source>Embed</source>
|
||||||
|
<translation>Einbetten</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>No file selected</source>
|
||||||
|
<translation type="vanished">Keine Datei gewählt</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUI.cpp" line="162"/>
|
||||||
|
<source>No file selected.</source>
|
||||||
|
<translation>Keine Datei gewählt.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUI.cpp" line="175"/>
|
||||||
|
<source>File not found.</source>
|
||||||
|
<translation>Datei nicht gefunden.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUI.cpp" line="178"/>
|
||||||
|
<source>Library could not be loaded.</source>
|
||||||
|
<translation>Bibliothek konnte nicht geladen werden.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUI.cpp" line="181"/>
|
||||||
|
<source>Library does not contain needed functions.</source>
|
||||||
|
<translation>Bibliothek enthält benötigte Funktionen nicht.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUI.cpp" line="189"/>
|
||||||
|
<source>Library has the wrong architecture. Only %1-bit libraries are supported.</source>
|
||||||
|
<translation>Bibliothek hat die falsche Architektur. Nur %1-bit-Bibliotheken werden unterstützt.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUI.cpp" line="210"/>
|
||||||
|
<source>Plugin crashed during initialization.</source>
|
||||||
|
<translation>Plugin ist bei der Initialisierung abgestürzt.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUI.cpp" line="271"/>
|
||||||
|
<source>Select VST plugin</source>
|
||||||
|
<translation>VST-Plugin wählen</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUI.cpp" line="273"/>
|
||||||
|
<source>VST plugins (*.dll)</source>
|
||||||
|
<translation>VST-Plugins (*.dll)</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUI.cpp" line="320"/>
|
||||||
|
<source>Plugin crashed when opening panel.</source>
|
||||||
|
<translation>Plugin ist beim Öffnen des Panels abgestürzt.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUI.cpp" line="418"/>
|
||||||
|
<source>The library is not readable by the audio service.
|
||||||
|
Change the file permissions or copy the file to the plugins directory.</source>
|
||||||
|
<translation>Die Bibliothek ist für den Audiodienst nicht lesbar.
|
||||||
|
Ändern Sie die Dateiberechtigungen oder kopieren Sie die Datei in das plugins-Verzeichnis.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUI.cpp" line="469"/>
|
||||||
|
<source>The plugin seemingly accesses these files not readable by the audio service:
|
||||||
|
%0
|
||||||
|
Change the file permissions or copy the files to the config directory.</source>
|
||||||
|
<translation>Das Plugin scheint auf diese für den Audiodienst nicht lesbaren Dateien zuzugreifen:
|
||||||
|
%0
|
||||||
|
Ändern Sie die Dateiberechtigungen oder kopieren Sie die Dateien in das config-Verzeichnis.</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>VSTPluginFilterGUIDialog</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUIDialog.ui" line="20"/>
|
||||||
|
<source>Apply automatically</source>
|
||||||
|
<translation>Automatisch anwenden</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>VSTPluginFilterGUIFactory</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUIFactory.cpp" line="32"/>
|
||||||
|
<source>VST plugin</source>
|
||||||
|
<translation>VST-Plugin</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../guis/VSTPluginFilterGUIFactory.cpp" line="32"/>
|
||||||
|
<source>Plugins</source>
|
||||||
|
<translation>Plugins</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
</TS>
|
</TS>
|
||||||
@@ -26,9 +26,13 @@ EscapableLineEdit::EscapableLineEdit(QWidget* parent)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EscapableLineEdit::EscapableLineEdit(const QString& text, QWidget* parent)
|
||||||
|
: QLineEdit(text, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void EscapableLineEdit::keyPressEvent(QKeyEvent* event)
|
void EscapableLineEdit::keyPressEvent(QKeyEvent* event)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (event->key() == Qt::Key_Escape)
|
if (event->key() == Qt::Key_Escape)
|
||||||
emit editingCanceled();
|
emit editingCanceled();
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ class EscapableLineEdit : public QLineEdit
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit EscapableLineEdit(QWidget* parent = 0);
|
explicit EscapableLineEdit(QWidget* parent = 0);
|
||||||
|
explicit EscapableLineEdit(const QString& text, QWidget* parent = 0);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void editingCanceled();
|
void editingCanceled();
|
||||||
|
|||||||
@@ -20,15 +20,15 @@
|
|||||||
#include "ResizingLineEdit.h"
|
#include "ResizingLineEdit.h"
|
||||||
|
|
||||||
ResizingLineEdit::ResizingLineEdit(QWidget* parent)
|
ResizingLineEdit::ResizingLineEdit(QWidget* parent)
|
||||||
: QLineEdit(parent)
|
: EscapableLineEdit(parent)
|
||||||
{
|
{
|
||||||
connect(this, SIGNAL(textChanged(QString)), this, SLOT(readjustSize()));
|
connect(this, SIGNAL(textChanged(QString)), this, SLOT(readjustSize()));
|
||||||
|
|
||||||
readjustSize();
|
readjustSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
ResizingLineEdit::ResizingLineEdit(const QString& text, QWidget* parent)
|
ResizingLineEdit::ResizingLineEdit(const QString& text, bool forceWidth, QWidget* parent)
|
||||||
: QLineEdit(text, parent)
|
: EscapableLineEdit(text, parent), forceWidth(forceWidth)
|
||||||
{
|
{
|
||||||
connect(this, SIGNAL(textChanged(QString)), this, SLOT(readjustSize()));
|
connect(this, SIGNAL(textChanged(QString)), this, SLOT(readjustSize()));
|
||||||
|
|
||||||
@@ -50,5 +50,8 @@ QSize ResizingLineEdit::sizeHint() const
|
|||||||
|
|
||||||
void ResizingLineEdit::readjustSize()
|
void ResizingLineEdit::readjustSize()
|
||||||
{
|
{
|
||||||
setFixedWidth(sizeHint().width());
|
if (forceWidth)
|
||||||
|
setFixedWidth(sizeHint().width());
|
||||||
|
else
|
||||||
|
setMinimumWidth(sizeHint().width());
|
||||||
}
|
}
|
||||||
@@ -19,17 +19,20 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QLineEdit>
|
#include "EscapableLineEdit.h"
|
||||||
|
|
||||||
class ResizingLineEdit : public QLineEdit
|
class ResizingLineEdit : public EscapableLineEdit
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit ResizingLineEdit(QWidget* parent = 0);
|
explicit ResizingLineEdit(QWidget* parent = 0);
|
||||||
explicit ResizingLineEdit(const QString& text, QWidget* parent = 0);
|
explicit ResizingLineEdit(const QString& text, bool forceWidth, QWidget* parent = 0);
|
||||||
|
|
||||||
QSize sizeHint() const override;
|
QSize sizeHint() const override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void readjustSize();
|
void readjustSize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool forceWidth = false;
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
extensions: .cpp .h
|
||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, a system-wide equalizer.
|
||||||
|
Copyright (C) %CurrentYear% 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.
|
||||||
|
*/
|
||||||
+16
-4
@@ -99,7 +99,7 @@
|
|||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>muparserxd.lib;audioeng.lib;version.lib;wmcodecdspuuid.lib;AudioBaseProcessingObject.lib;audiomediatypecrt.lib;Shlwapi.lib;authz.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>muparserxd.lib;audioeng.lib;version.lib;wmcodecdspuuid.lib;AudioBaseProcessingObject.lib;audiomediatypecrt.lib;Shlwapi.lib;authz.lib;crypt32.lib;dbghelp.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<ModuleDefinitionFile>EqualizerAPO.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>EqualizerAPO.def</ModuleDefinitionFile>
|
||||||
</Link>
|
</Link>
|
||||||
<Midl>
|
<Midl>
|
||||||
@@ -116,7 +116,7 @@
|
|||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>muparserxd.lib;audioeng.lib;version.lib;wmcodecdspuuid.lib;AudioBaseProcessingObject.lib;audiomediatypecrt.lib;Shlwapi.lib;authz.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>muparserxd.lib;audioeng.lib;version.lib;wmcodecdspuuid.lib;AudioBaseProcessingObject.lib;audiomediatypecrt.lib;Shlwapi.lib;authz.lib;crypt32.lib;dbghelp.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<ModuleDefinitionFile>EqualizerAPO.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>EqualizerAPO.def</ModuleDefinitionFile>
|
||||||
</Link>
|
</Link>
|
||||||
<Midl>
|
<Midl>
|
||||||
@@ -138,7 +138,7 @@
|
|||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>muparserx.lib;audioeng.lib;version.lib;wmcodecdspuuid.lib;AudioBaseProcessingObject.lib;audiomediatypecrt.lib;Shlwapi.lib;authz.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>muparserx.lib;audioeng.lib;version.lib;wmcodecdspuuid.lib;AudioBaseProcessingObject.lib;audiomediatypecrt.lib;Shlwapi.lib;authz.lib;crypt32.lib;dbghelp.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<ModuleDefinitionFile>EqualizerAPO.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>EqualizerAPO.def</ModuleDefinitionFile>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@@ -157,7 +157,7 @@
|
|||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>muparserx.lib;audioeng.lib;version.lib;wmcodecdspuuid.lib;AudioBaseProcessingObject.lib;audiomediatypecrt.lib;Shlwapi.lib;authz.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>muparserx.lib;audioeng.lib;version.lib;wmcodecdspuuid.lib;AudioBaseProcessingObject.lib;audiomediatypecrt.lib;Shlwapi.lib;authz.lib;crypt32.lib;dbghelp.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<ModuleDefinitionFile>EqualizerAPO.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>EqualizerAPO.def</ModuleDefinitionFile>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@@ -190,6 +190,10 @@
|
|||||||
<ClInclude Include="filters\PreampFilter.h" />
|
<ClInclude Include="filters\PreampFilter.h" />
|
||||||
<ClInclude Include="filters\PreampFilterFactory.h" />
|
<ClInclude Include="filters\PreampFilterFactory.h" />
|
||||||
<ClInclude Include="filters\StageFilterFactory.h" />
|
<ClInclude Include="filters\StageFilterFactory.h" />
|
||||||
|
<ClInclude Include="filters\VSTPluginFilter.h" />
|
||||||
|
<ClInclude Include="filters\VSTPluginFilterFactory.h" />
|
||||||
|
<ClInclude Include="helpers\AbstractLibrary.h" />
|
||||||
|
<ClInclude Include="helpers\aeffectx.h" />
|
||||||
<ClInclude Include="helpers\ChannelHelper.h" />
|
<ClInclude Include="helpers\ChannelHelper.h" />
|
||||||
<ClInclude Include="helpers\GainIterator.h" />
|
<ClInclude Include="helpers\GainIterator.h" />
|
||||||
<ClInclude Include="helpers\LogHelper.h" />
|
<ClInclude Include="helpers\LogHelper.h" />
|
||||||
@@ -199,6 +203,8 @@
|
|||||||
<ClInclude Include="helpers\ScopeGuard.h" />
|
<ClInclude Include="helpers\ScopeGuard.h" />
|
||||||
<ClInclude Include="helpers\StringHelper.h" />
|
<ClInclude Include="helpers\StringHelper.h" />
|
||||||
<ClInclude Include="helpers\UncaughtExceptions.h" />
|
<ClInclude Include="helpers\UncaughtExceptions.h" />
|
||||||
|
<ClInclude Include="helpers\VSTPluginInstance.h" />
|
||||||
|
<ClInclude Include="helpers\VSTPluginLibrary.h" />
|
||||||
<ClInclude Include="IFilter.h" />
|
<ClInclude Include="IFilter.h" />
|
||||||
<ClInclude Include="IFilterFactory.h" />
|
<ClInclude Include="IFilterFactory.h" />
|
||||||
<ClInclude Include="libHybridConv-0.1.1\libHybridConv_eapo.h" />
|
<ClInclude Include="libHybridConv-0.1.1\libHybridConv_eapo.h" />
|
||||||
@@ -240,12 +246,17 @@
|
|||||||
<ClCompile Include="filters\PreampFilter.cpp" />
|
<ClCompile Include="filters\PreampFilter.cpp" />
|
||||||
<ClCompile Include="filters\PreampFilterFactory.cpp" />
|
<ClCompile Include="filters\PreampFilterFactory.cpp" />
|
||||||
<ClCompile Include="filters\StageFilterFactory.cpp" />
|
<ClCompile Include="filters\StageFilterFactory.cpp" />
|
||||||
|
<ClCompile Include="filters\VSTPluginFilter.cpp" />
|
||||||
|
<ClCompile Include="filters\VSTPluginFilterFactory.cpp" />
|
||||||
|
<ClCompile Include="helpers\AbstractLibrary.cpp" />
|
||||||
<ClCompile Include="helpers\ChannelHelper.cpp" />
|
<ClCompile Include="helpers\ChannelHelper.cpp" />
|
||||||
<ClCompile Include="helpers\GainIterator.cpp" />
|
<ClCompile Include="helpers\GainIterator.cpp" />
|
||||||
<ClCompile Include="helpers\LogHelper.cpp" />
|
<ClCompile Include="helpers\LogHelper.cpp" />
|
||||||
<ClCompile Include="helpers\MemoryHelper.cpp" />
|
<ClCompile Include="helpers\MemoryHelper.cpp" />
|
||||||
<ClCompile Include="helpers\RegistryHelper.cpp" />
|
<ClCompile Include="helpers\RegistryHelper.cpp" />
|
||||||
<ClCompile Include="helpers\StringHelper.cpp" />
|
<ClCompile Include="helpers\StringHelper.cpp" />
|
||||||
|
<ClCompile Include="helpers\VSTPluginInstance.cpp" />
|
||||||
|
<ClCompile Include="helpers\VSTPluginLibrary.cpp" />
|
||||||
<ClCompile Include="IFilter.cpp" />
|
<ClCompile Include="IFilter.cpp" />
|
||||||
<ClCompile Include="libHybridConv-0.1.1\libHybridConv_eapo.cpp" />
|
<ClCompile Include="libHybridConv-0.1.1\libHybridConv_eapo.cpp" />
|
||||||
<ClCompile Include="parser\RegexFunctions.cpp" />
|
<ClCompile Include="parser\RegexFunctions.cpp" />
|
||||||
@@ -261,6 +272,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="EqualizerAPO.def" />
|
<None Include="EqualizerAPO.def" />
|
||||||
|
<None Include="EqualizerAPO.licenseheader" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="EqualizerAPO.rc">
|
<ResourceCompile Include="EqualizerAPO.rc">
|
||||||
|
|||||||
@@ -107,6 +107,21 @@
|
|||||||
<ClCompile Include="stdafx.cpp" />
|
<ClCompile Include="stdafx.cpp" />
|
||||||
<ClCompile Include="AbstractAPOInfo.cpp" />
|
<ClCompile Include="AbstractAPOInfo.cpp" />
|
||||||
<ClCompile Include="VoicemeeterAPOInfo.cpp" />
|
<ClCompile Include="VoicemeeterAPOInfo.cpp" />
|
||||||
|
<ClCompile Include="helpers\AbstractLibrary.cpp">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="filters\VSTPluginFilter.cpp">
|
||||||
|
<Filter>filters</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="filters\VSTPluginFilterFactory.cpp">
|
||||||
|
<Filter>filters</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="helpers\VSTPluginLibrary.cpp">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="helpers\VSTPluginInstance.cpp">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="ClassFactory.h" />
|
<ClInclude Include="ClassFactory.h" />
|
||||||
@@ -226,6 +241,24 @@
|
|||||||
<Filter>helpers</Filter>
|
<Filter>helpers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="VoicemeeterAPOInfo.h" />
|
<ClInclude Include="VoicemeeterAPOInfo.h" />
|
||||||
|
<ClInclude Include="helpers\AbstractLibrary.h">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="helpers\aeffectx.h">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="filters\VSTPluginFilter.h">
|
||||||
|
<Filter>filters</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="filters\VSTPluginFilterFactory.h">
|
||||||
|
<Filter>filters</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="helpers\VSTPluginLibrary.h">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="helpers\VSTPluginInstance.h">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="EqualizerAPO.rc" />
|
<ResourceCompile Include="EqualizerAPO.rc" />
|
||||||
@@ -233,6 +266,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="EqualizerAPO.def" />
|
<None Include="EqualizerAPO.def" />
|
||||||
|
<None Include="EqualizerAPO.licenseheader" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="filters">
|
<Filter Include="filters">
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
#include "filters/IncludeFilterFactory.h"
|
#include "filters/IncludeFilterFactory.h"
|
||||||
#include "filters/ConvolutionFilterFactory.h"
|
#include "filters/ConvolutionFilterFactory.h"
|
||||||
#include "filters/GraphicEQFilterFactory.h"
|
#include "filters/GraphicEQFilterFactory.h"
|
||||||
|
#include "filters/VSTPluginFilterFactory.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace mup;
|
using namespace mup;
|
||||||
@@ -87,6 +88,7 @@ FilterEngine::FilterEngine()
|
|||||||
factories.push_back(new CopyFilterFactory());
|
factories.push_back(new CopyFilterFactory());
|
||||||
factories.push_back(new ConvolutionFilterFactory());
|
factories.push_back(new ConvolutionFilterFactory());
|
||||||
factories.push_back(new GraphicEQFilterFactory());
|
factories.push_back(new GraphicEQFilterFactory());
|
||||||
|
factories.push_back(new VSTPluginFilterFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
FilterEngine::~FilterEngine()
|
FilterEngine::~FilterEngine()
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public:
|
|||||||
|
|
||||||
// request to get all channel names instead of selection
|
// request to get all channel names instead of selection
|
||||||
virtual bool getAllChannels() {return false;}
|
virtual bool getAllChannels() {return false;}
|
||||||
// request that output and input do not point to the same memory locations
|
// return false to request that output and input do not point to the same memory locations
|
||||||
virtual bool getInPlace() {return true;}
|
virtual bool getInPlace() {return true;}
|
||||||
// request that the channelNames returned by initialize become the new selection
|
// request that the channelNames returned by initialize become the new selection
|
||||||
virtual bool getSelectChannels() {return false;}
|
virtual bool getSelectChannels() {return false;}
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ Section "Install" SecInstall
|
|||||||
File "Configuration reference (online).url"
|
File "Configuration reference (online).url"
|
||||||
|
|
||||||
CreateDirectory "$INSTDIR\config"
|
CreateDirectory "$INSTDIR\config"
|
||||||
|
CreateDirectory "$INSTDIR\plugins"
|
||||||
|
|
||||||
SetOverwrite off
|
SetOverwrite off
|
||||||
File /oname=config\config.txt "config\config.txt"
|
File /oname=config\config.txt "config\config.txt"
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 "stdafx.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@@ -96,7 +96,7 @@
|
|||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>muparserxd.lib;version.lib;Shlwapi.lib;authz.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>muparserxd.lib;version.lib;Shlwapi.lib;authz.lib;crypt32.lib;dbghelp.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@@ -109,7 +109,7 @@
|
|||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>muparserxd.lib;version.lib;Shlwapi.lib;authz.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>muparserxd.lib;version.lib;Shlwapi.lib;authz.lib;crypt32.lib;dbghelp.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@@ -127,7 +127,7 @@
|
|||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>muparserx.lib;version.lib;Shlwapi.lib;authz.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>muparserx.lib;version.lib;Shlwapi.lib;authz.lib;crypt32.lib;dbghelp.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>muparserx.lib;version.lib;Shlwapi.lib;authz.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>muparserx.lib;version.lib;Shlwapi.lib;authz.lib;crypt32.lib;dbghelp.lib;libsndfile-1.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -175,6 +175,9 @@
|
|||||||
<ClInclude Include="..\filters\PreampFilter.h" />
|
<ClInclude Include="..\filters\PreampFilter.h" />
|
||||||
<ClInclude Include="..\filters\PreampFilterFactory.h" />
|
<ClInclude Include="..\filters\PreampFilterFactory.h" />
|
||||||
<ClInclude Include="..\filters\StageFilterFactory.h" />
|
<ClInclude Include="..\filters\StageFilterFactory.h" />
|
||||||
|
<ClInclude Include="..\filters\VSTPluginFilter.h" />
|
||||||
|
<ClInclude Include="..\filters\VSTPluginFilterFactory.h" />
|
||||||
|
<ClInclude Include="..\helpers\AbstractLibrary.h" />
|
||||||
<ClInclude Include="..\helpers\ChannelHelper.h" />
|
<ClInclude Include="..\helpers\ChannelHelper.h" />
|
||||||
<ClInclude Include="..\helpers\GainIterator.h" />
|
<ClInclude Include="..\helpers\GainIterator.h" />
|
||||||
<ClInclude Include="..\helpers\LogHelper.h" />
|
<ClInclude Include="..\helpers\LogHelper.h" />
|
||||||
@@ -183,6 +186,8 @@
|
|||||||
<ClInclude Include="..\helpers\ScopeGuard.h" />
|
<ClInclude Include="..\helpers\ScopeGuard.h" />
|
||||||
<ClInclude Include="..\helpers\StringHelper.h" />
|
<ClInclude Include="..\helpers\StringHelper.h" />
|
||||||
<ClInclude Include="..\helpers\UncaughtExceptions.h" />
|
<ClInclude Include="..\helpers\UncaughtExceptions.h" />
|
||||||
|
<ClInclude Include="..\helpers\VSTPluginInstance.h" />
|
||||||
|
<ClInclude Include="..\helpers\VSTPluginLibrary.h" />
|
||||||
<ClInclude Include="..\IFilter.h" />
|
<ClInclude Include="..\IFilter.h" />
|
||||||
<ClInclude Include="..\IFilterFactory.h" />
|
<ClInclude Include="..\IFilterFactory.h" />
|
||||||
<ClInclude Include="..\libHybridConv-0.1.1\libHybridConv_eapo.h" />
|
<ClInclude Include="..\libHybridConv-0.1.1\libHybridConv_eapo.h" />
|
||||||
@@ -220,12 +225,17 @@
|
|||||||
<ClCompile Include="..\filters\PreampFilter.cpp" />
|
<ClCompile Include="..\filters\PreampFilter.cpp" />
|
||||||
<ClCompile Include="..\filters\PreampFilterFactory.cpp" />
|
<ClCompile Include="..\filters\PreampFilterFactory.cpp" />
|
||||||
<ClCompile Include="..\filters\StageFilterFactory.cpp" />
|
<ClCompile Include="..\filters\StageFilterFactory.cpp" />
|
||||||
|
<ClCompile Include="..\filters\VSTPluginFilter.cpp" />
|
||||||
|
<ClCompile Include="..\filters\VSTPluginFilterFactory.cpp" />
|
||||||
|
<ClCompile Include="..\helpers\AbstractLibrary.cpp" />
|
||||||
<ClCompile Include="..\helpers\ChannelHelper.cpp" />
|
<ClCompile Include="..\helpers\ChannelHelper.cpp" />
|
||||||
<ClCompile Include="..\helpers\GainIterator.cpp" />
|
<ClCompile Include="..\helpers\GainIterator.cpp" />
|
||||||
<ClCompile Include="..\helpers\LogHelper.cpp" />
|
<ClCompile Include="..\helpers\LogHelper.cpp" />
|
||||||
<ClCompile Include="..\helpers\MemoryHelper.cpp" />
|
<ClCompile Include="..\helpers\MemoryHelper.cpp" />
|
||||||
<ClCompile Include="..\helpers\RegistryHelper.cpp" />
|
<ClCompile Include="..\helpers\RegistryHelper.cpp" />
|
||||||
<ClCompile Include="..\helpers\StringHelper.cpp" />
|
<ClCompile Include="..\helpers\StringHelper.cpp" />
|
||||||
|
<ClCompile Include="..\helpers\VSTPluginInstance.cpp" />
|
||||||
|
<ClCompile Include="..\helpers\VSTPluginLibrary.cpp" />
|
||||||
<ClCompile Include="..\IFilter.cpp" />
|
<ClCompile Include="..\IFilter.cpp" />
|
||||||
<ClCompile Include="..\libHybridConv-0.1.1\libHybridConv_eapo.cpp" />
|
<ClCompile Include="..\libHybridConv-0.1.1\libHybridConv_eapo.cpp" />
|
||||||
<ClCompile Include="..\parser\RegexFunctions.cpp" />
|
<ClCompile Include="..\parser\RegexFunctions.cpp" />
|
||||||
@@ -243,6 +253,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="VoicemeeterClient.rc" />
|
<ResourceCompile Include="VoicemeeterClient.rc" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\EqualizerAPO.licenseheader" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
|||||||
@@ -127,6 +127,21 @@
|
|||||||
<ClInclude Include="..\helpers\UncaughtExceptions.h">
|
<ClInclude Include="..\helpers\UncaughtExceptions.h">
|
||||||
<Filter>helpers</Filter>
|
<Filter>helpers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\helpers\AbstractLibrary.h">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\filters\VSTPluginFilter.h">
|
||||||
|
<Filter>filters</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\filters\VSTPluginFilterFactory.h">
|
||||||
|
<Filter>filters</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\helpers\VSTPluginLibrary.h">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\helpers\VSTPluginInstance.h">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\helpers\RegistryHelper.cpp">
|
<ClCompile Include="..\helpers\RegistryHelper.cpp">
|
||||||
@@ -232,8 +247,26 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\VoicemeeterAPOInfo.cpp" />
|
<ClCompile Include="..\VoicemeeterAPOInfo.cpp" />
|
||||||
<ClCompile Include="..\AbstractAPOInfo.cpp" />
|
<ClCompile Include="..\AbstractAPOInfo.cpp" />
|
||||||
|
<ClCompile Include="..\helpers\AbstractLibrary.cpp">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\filters\VSTPluginFilter.cpp">
|
||||||
|
<Filter>filters</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\filters\VSTPluginFilterFactory.cpp">
|
||||||
|
<Filter>filters</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\helpers\VSTPluginLibrary.cpp">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\helpers\VSTPluginInstance.cpp">
|
||||||
|
<Filter>helpers</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="VoicemeeterClient.rc" />
|
<ResourceCompile Include="VoicemeeterClient.rc" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\EqualizerAPO.licenseheader" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -0,0 +1,234 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 "helpers/StringHelper.h"
|
||||||
|
#include "helpers/LogHelper.h"
|
||||||
|
#include "VSTPluginFilter.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
VSTPluginFilter::VSTPluginFilter(std::shared_ptr<VSTPluginLibrary> library, std::wstring chunkData, std::unordered_map<std::wstring, float> paramMap)
|
||||||
|
: library(library), chunkData(chunkData), paramMap(paramMap)
|
||||||
|
{
|
||||||
|
libPath = library->getLibPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
VSTPluginFilter::~VSTPluginFilter()
|
||||||
|
{
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::wstring> VSTPluginFilter::initialize(float sampleRate, unsigned maxFrameCount, std::vector<std::wstring> channelNames)
|
||||||
|
{
|
||||||
|
cleanup();
|
||||||
|
|
||||||
|
channelCount = channelNames.size();
|
||||||
|
if (channelCount == 0)
|
||||||
|
return channelNames;
|
||||||
|
|
||||||
|
skipProcessing = false;
|
||||||
|
|
||||||
|
void* mem = MemoryHelper::alloc(sizeof(VSTPluginInstance));
|
||||||
|
VSTPluginInstance* firstEffect = new(mem) VSTPluginInstance(library, 2);
|
||||||
|
if (!firstEffect->initialize())
|
||||||
|
{
|
||||||
|
LogF(L"The VST plugin %s crashed during initialization.", libPath.c_str());
|
||||||
|
skipProcessing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
effectChannelCount = max(firstEffect->numInputs(), firstEffect->numOutputs());
|
||||||
|
// round up
|
||||||
|
effectCount = (channelCount + (effectChannelCount - 1)) / effectChannelCount;
|
||||||
|
effects = (VSTPluginInstance**)MemoryHelper::alloc(effectCount * sizeof(VSTPluginInstance*));
|
||||||
|
effects[0] = firstEffect;
|
||||||
|
for (unsigned i = 1; i < effectCount; i++)
|
||||||
|
{
|
||||||
|
mem = MemoryHelper::alloc(sizeof(VSTPluginInstance));
|
||||||
|
effects[i] = new(mem) VSTPluginInstance(library, 2);
|
||||||
|
if (!effects[i]->initialize() && !skipProcessing)
|
||||||
|
{
|
||||||
|
LogF(L"The VST plugin %s crashed during initialization.", libPath.c_str());
|
||||||
|
skipProcessing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareForProcessing(sampleRate, maxFrameCount);
|
||||||
|
|
||||||
|
// 2 times for input and output
|
||||||
|
emptyChannelCount = 2 * (effectCount * effectChannelCount - channelCount);
|
||||||
|
emptyChannels = (float**)MemoryHelper::alloc(emptyChannelCount * sizeof(float*));
|
||||||
|
for (unsigned i = 0; i < emptyChannelCount; i++)
|
||||||
|
{
|
||||||
|
emptyChannels[i] = (float*)MemoryHelper::alloc(maxFrameCount * sizeof(float));
|
||||||
|
memset(emptyChannels[i], 0, maxFrameCount * sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
inputArray = (float**)MemoryHelper::alloc(firstEffect->numInputs() * sizeof(float*));
|
||||||
|
outputArray = (float**)MemoryHelper::alloc(firstEffect->numOutputs() * sizeof(float*));
|
||||||
|
|
||||||
|
return channelNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilter::prepareForProcessing(float sampleRate, unsigned maxFrameCount)
|
||||||
|
{
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < effectCount; i++)
|
||||||
|
{
|
||||||
|
VSTPluginInstance* effect = effects[i];
|
||||||
|
|
||||||
|
if (i == effectCount - 1 && (channelCount % effectChannelCount) != 0)
|
||||||
|
effect->setUsedChannelCount(channelCount % effectChannelCount);
|
||||||
|
else
|
||||||
|
effect->setUsedChannelCount(effectChannelCount);
|
||||||
|
effect->prepareForProcessing(sampleRate, maxFrameCount);
|
||||||
|
effect->writeToEffect(chunkData, paramMap);
|
||||||
|
effect->startProcessing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
LogF(L"The VST plugin %s crashed while preparing for processing.", libPath.c_str());
|
||||||
|
skipProcessing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma AVRT_CODE_BEGIN
|
||||||
|
void VSTPluginFilter::process(float** output, float** input, unsigned frameCount)
|
||||||
|
{
|
||||||
|
if (skipProcessing)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < channelCount; i++)
|
||||||
|
memcpy(output[i], input[i], frameCount * sizeof(float));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
unsigned channelOffset = 0;
|
||||||
|
unsigned emptyChannelIndex = 0;
|
||||||
|
for (unsigned i = 0; i < effectCount; i++)
|
||||||
|
{
|
||||||
|
VSTPluginInstance* effect = effects[i];
|
||||||
|
for (int j = 0; j < effect->numInputs(); j++)
|
||||||
|
{
|
||||||
|
if (channelOffset + j < channelCount)
|
||||||
|
inputArray[j] = input[channelOffset + j];
|
||||||
|
else
|
||||||
|
inputArray[j] = emptyChannels[emptyChannelIndex++];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < effect->numOutputs(); j++)
|
||||||
|
{
|
||||||
|
if (channelOffset + j < channelCount)
|
||||||
|
outputArray[j] = output[channelOffset + j];
|
||||||
|
else
|
||||||
|
outputArray[j] = emptyChannels[emptyChannelIndex++];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (effect->canReplacing())
|
||||||
|
{
|
||||||
|
effect->processReplacing(inputArray, outputArray, frameCount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int j = 0; j < effect->numOutputs(); j++)
|
||||||
|
memset(outputArray[j], 0, frameCount * sizeof(float));
|
||||||
|
effect->process(inputArray, outputArray, frameCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (effect->numOutputs() < effect->numInputs())
|
||||||
|
{
|
||||||
|
for (int j = effect->numOutputs(); j < effect->numInputs(); j++)
|
||||||
|
{
|
||||||
|
if (channelOffset + j < channelCount)
|
||||||
|
memset(output[channelOffset + j], 0, frameCount * sizeof(float));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
channelOffset += effectChannelCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
if (reportCrash)
|
||||||
|
{
|
||||||
|
LogF(L"The VST plugin %s crashed during audio processing.", libPath.c_str());
|
||||||
|
reportCrash = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < channelCount; i++)
|
||||||
|
memcpy(output[i], input[i], frameCount * sizeof(float));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#pragma AVRT_CODE_END
|
||||||
|
|
||||||
|
std::shared_ptr<VSTPluginLibrary> VSTPluginFilter::getLibrary() const
|
||||||
|
{
|
||||||
|
return library;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring VSTPluginFilter::getChunkData() const
|
||||||
|
{
|
||||||
|
return chunkData;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_map<std::wstring, float> VSTPluginFilter::getParamMap() const
|
||||||
|
{
|
||||||
|
return paramMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginFilter::cleanup()
|
||||||
|
{
|
||||||
|
if (effects != NULL)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < effectCount; i++)
|
||||||
|
{
|
||||||
|
VSTPluginInstance* effect = effects[i];
|
||||||
|
effect->stopProcessing();
|
||||||
|
effect->~VSTPluginInstance();
|
||||||
|
MemoryHelper::free(effect);
|
||||||
|
}
|
||||||
|
MemoryHelper::free(effects);
|
||||||
|
effects = NULL;
|
||||||
|
}
|
||||||
|
effectCount = 0;
|
||||||
|
|
||||||
|
if (emptyChannels != NULL)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < emptyChannelCount; i++)
|
||||||
|
MemoryHelper::free(emptyChannels[i]);
|
||||||
|
MemoryHelper::free(emptyChannels);
|
||||||
|
emptyChannels = NULL;
|
||||||
|
}
|
||||||
|
emptyChannelCount = 0;
|
||||||
|
|
||||||
|
if (inputArray != NULL)
|
||||||
|
{
|
||||||
|
MemoryHelper::free(inputArray);
|
||||||
|
inputArray = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outputArray != NULL)
|
||||||
|
{
|
||||||
|
MemoryHelper::free(outputArray);
|
||||||
|
outputArray = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 "IFilter.h"
|
||||||
|
#include "helpers/VSTPluginLibrary.h"
|
||||||
|
|
||||||
|
#pragma AVRT_VTABLES_BEGIN
|
||||||
|
class VSTPluginFilter : public IFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VSTPluginFilter(std::shared_ptr<VSTPluginLibrary> library, std::wstring chunkData, std::unordered_map<std::wstring, float> paramMap);
|
||||||
|
~VSTPluginFilter();
|
||||||
|
|
||||||
|
bool getInPlace() override {return false;}
|
||||||
|
std::vector<std::wstring> initialize(float sampleRate, unsigned maxFrameCount, std::vector<std::wstring> channelNames) override;
|
||||||
|
void prepareForProcessing(float sampleRate, unsigned maxFrameCount);
|
||||||
|
void process(float** output, float** input, unsigned frameCount) override;
|
||||||
|
|
||||||
|
std::shared_ptr<VSTPluginLibrary> getLibrary() const;
|
||||||
|
std::wstring getChunkData() const;
|
||||||
|
std::unordered_map<std::wstring, float> getParamMap() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void cleanup();
|
||||||
|
|
||||||
|
std::shared_ptr<VSTPluginLibrary> library;
|
||||||
|
std::wstring libPath;
|
||||||
|
std::wstring chunkData;
|
||||||
|
std::unordered_map<std::wstring, float> paramMap;
|
||||||
|
size_t channelCount;
|
||||||
|
unsigned effectChannelCount;
|
||||||
|
size_t effectCount = 0;
|
||||||
|
VSTPluginInstance** effects = NULL;
|
||||||
|
size_t emptyChannelCount = 0;
|
||||||
|
float** emptyChannels = NULL;
|
||||||
|
float** inputArray = NULL;
|
||||||
|
float** outputArray = NULL;
|
||||||
|
bool skipProcessing = false;
|
||||||
|
bool reportCrash = true;
|
||||||
|
};
|
||||||
|
#pragma AVRT_VTABLES_END
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 "helpers/StringHelper.h"
|
||||||
|
#include "helpers/VSTPluginLibrary.h"
|
||||||
|
#include "helpers/LogHelper.h"
|
||||||
|
#include "VSTPluginFilter.h"
|
||||||
|
#include "VSTPluginFilterFactory.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
vector<IFilter*> VSTPluginFilterFactory::createFilter(const wstring& configPath, wstring& command, wstring& parameters)
|
||||||
|
{
|
||||||
|
VSTPluginFilter* filter = NULL;
|
||||||
|
|
||||||
|
if (command == L"VSTPlugin")
|
||||||
|
{
|
||||||
|
shared_ptr<VSTPluginLibrary> library;
|
||||||
|
wstring chunkData;
|
||||||
|
unordered_map<wstring, float> paramMap;
|
||||||
|
vector<wstring> parts = StringHelper::splitQuoted(parameters, ' ');
|
||||||
|
for (unsigned i = 0; i + 1 < parts.size(); i += 2)
|
||||||
|
{
|
||||||
|
wstring key = parts[i];
|
||||||
|
wstring value = parts[i + 1];
|
||||||
|
|
||||||
|
if (key == L"Library")
|
||||||
|
{
|
||||||
|
wstring libPath;
|
||||||
|
if (PathIsRelativeW(value.c_str()))
|
||||||
|
{
|
||||||
|
wchar_t filePath[MAX_PATH];
|
||||||
|
wstring pluginPath = VSTPluginLibrary::getDefaultPluginPath();
|
||||||
|
pluginPath._Copy_s(filePath, sizeof(filePath) / sizeof(wchar_t), MAX_PATH);
|
||||||
|
if (pluginPath.size() < MAX_PATH)
|
||||||
|
filePath[pluginPath.size()] = L'\0';
|
||||||
|
else
|
||||||
|
filePath[MAX_PATH - 1] = L'\0';
|
||||||
|
PathAppendW(filePath, value.c_str());
|
||||||
|
libPath = filePath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
libPath = value;
|
||||||
|
|
||||||
|
library = VSTPluginLibrary::getInstance(libPath);
|
||||||
|
}
|
||||||
|
else if (key == L"ChunkData")
|
||||||
|
{
|
||||||
|
chunkData = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float f = wcstof(value.c_str(), NULL);
|
||||||
|
paramMap[key] = f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (library != NULL)
|
||||||
|
{
|
||||||
|
bool create = true;
|
||||||
|
if (configPath != L"")
|
||||||
|
{
|
||||||
|
create = false;
|
||||||
|
TraceF(L"Adding VST plugin %s", library->getLibPath().c_str());
|
||||||
|
int res = library->initialize();
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
#ifdef _WIN64
|
||||||
|
int bitDepth = 64;
|
||||||
|
#else
|
||||||
|
int bitDepth = 32;
|
||||||
|
#endif
|
||||||
|
if (res == AbstractLibrary::FILE_NOT_FOUND)
|
||||||
|
LogF(L"File %s not found", library->getLibPath());
|
||||||
|
else if (res == AbstractLibrary::LOADING_FAILED)
|
||||||
|
LogF(L"Library %s could not be loaded", library->getLibPath());
|
||||||
|
else if (res == AbstractLibrary::FUNCTIONS_MISSING)
|
||||||
|
LogF(L"Library %s does not contain needed functions", library->getLibPath());
|
||||||
|
else if (res == AbstractLibrary::WRONG_ARCHITECTURE)
|
||||||
|
LogF(L"Library %s has wrong architecture, must be %d-bit", library->getLibPath(), bitDepth);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
create = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (create)
|
||||||
|
{
|
||||||
|
void* mem = MemoryHelper::alloc(sizeof(VSTPluginFilter));
|
||||||
|
filter = new(mem) VSTPluginFilter(library, chunkData, paramMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter == NULL)
|
||||||
|
return vector<IFilter*>(0);
|
||||||
|
return vector<IFilter*>(1, filter);
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 "IFilterFactory.h"
|
||||||
|
#include "IFilter.h"
|
||||||
|
|
||||||
|
class VSTPluginFilterFactory : public IFilterFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector<IFilter*> createFilter(const std::wstring& configPath, std::wstring& command, std::wstring& parameters) override;
|
||||||
|
};
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 <Imagehlp.h>
|
||||||
|
#include "AbstractLibrary.h"
|
||||||
|
#include "helpers/LogHelper.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
AbstractLibrary::~AbstractLibrary()
|
||||||
|
{
|
||||||
|
if (module != NULL)
|
||||||
|
{
|
||||||
|
wchar_t path[MAX_PATH];
|
||||||
|
GetModuleFileNameW(module, path, MAX_PATH);
|
||||||
|
|
||||||
|
FreeLibrary(module);
|
||||||
|
module = NULL;
|
||||||
|
|
||||||
|
TraceF(L"Unloaded library %s", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int AbstractLibrary::initialize()
|
||||||
|
{
|
||||||
|
if (module == NULL)
|
||||||
|
{
|
||||||
|
wstring libPath = getLibPath();
|
||||||
|
if (GetFileAttributesW(libPath.c_str()) == INVALID_FILE_ATTRIBUTES)
|
||||||
|
return FILE_NOT_FOUND;
|
||||||
|
module = LoadLibraryW(libPath.c_str());
|
||||||
|
if (module == NULL)
|
||||||
|
{
|
||||||
|
unsigned short arch = getFileArchitecture(libPath);
|
||||||
|
#ifdef _WIN64
|
||||||
|
int bitDepth = 64;
|
||||||
|
#else
|
||||||
|
int bitDepth = 32;
|
||||||
|
#endif
|
||||||
|
if (arch != 0 && (bitDepth == 64 && arch != IMAGE_FILE_MACHINE_AMD64
|
||||||
|
|| bitDepth == 32 && arch != IMAGE_FILE_MACHINE_I386))
|
||||||
|
return WRONG_ARCHITECTURE;
|
||||||
|
|
||||||
|
return LOADING_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!loadFunctions())
|
||||||
|
{
|
||||||
|
FreeLibrary(module);
|
||||||
|
module = NULL;
|
||||||
|
return FUNCTIONS_MISSING;
|
||||||
|
}
|
||||||
|
|
||||||
|
int res = customInitialize();
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
TraceF(L"Loaded library %s", libPath.c_str());
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AbstractLibrary::customInitialize()
|
||||||
|
{
|
||||||
|
// overwrite if needed
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short AbstractLibrary::getFileArchitecture(const wstring& filePath)
|
||||||
|
{
|
||||||
|
unsigned short result = 0;
|
||||||
|
|
||||||
|
HANDLE hFile = CreateFileW(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (hFile != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
HANDLE hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||||
|
if (hMap != NULL)
|
||||||
|
{
|
||||||
|
void* mapAddr = MapViewOfFileEx(hMap, FILE_MAP_READ, 0, 0, 0, NULL);
|
||||||
|
if (mapAddr != NULL)
|
||||||
|
{
|
||||||
|
PIMAGE_NT_HEADERS ntHeaders = ImageNtHeader(mapAddr);
|
||||||
|
if (ntHeaders != NULL)
|
||||||
|
result = ntHeaders->FileHeader.Machine;
|
||||||
|
UnmapViewOfFile(mapAddr);
|
||||||
|
}
|
||||||
|
CloseHandle(hMap);
|
||||||
|
}
|
||||||
|
CloseHandle(hFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 AbstractLibrary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const int FILE_NOT_FOUND = -1;
|
||||||
|
static const int LOADING_FAILED = -2;
|
||||||
|
static const int FUNCTIONS_MISSING = -3;
|
||||||
|
static const int WRONG_ARCHITECTURE = -4;
|
||||||
|
|
||||||
|
virtual ~AbstractLibrary();
|
||||||
|
|
||||||
|
int initialize();
|
||||||
|
virtual std::wstring getLibPath() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool loadFunctions() = 0;
|
||||||
|
virtual int customInitialize();
|
||||||
|
|
||||||
|
HMODULE module = NULL;
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned short getFileArchitecture(const std::wstring& filePath);
|
||||||
|
};
|
||||||
@@ -85,7 +85,11 @@ double GainIterator::gainAt(double freq)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
double t = (log(freq) - logLeft) / logRightMinusLeft;
|
double t = (log(freq) - logLeft) / logRightMinusLeft;
|
||||||
dbGain = nodeLeft->dbGain + t * (nodeRight->dbGain - nodeLeft->dbGain);
|
// to support dbGain == -INF for both nodes
|
||||||
|
if (nodeLeft->dbGain == nodeRight->dbGain)
|
||||||
|
dbGain = nodeLeft->dbGain;
|
||||||
|
else
|
||||||
|
dbGain = nodeLeft->dbGain + t * (nodeRight->dbGain - nodeLeft->dbGain);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dbGain;
|
return dbGain;
|
||||||
|
|||||||
@@ -109,6 +109,8 @@ void LogHelper::log(const char* file, int line, const void* caller, bool trace,
|
|||||||
|
|
||||||
if (presetFP == NULL)
|
if (presetFP == NULL)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
else
|
||||||
|
fflush(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogHelper::reset()
|
void LogHelper::reset()
|
||||||
|
|||||||
@@ -163,3 +163,37 @@ wstring StringHelper::getSystemErrorString(long status)
|
|||||||
else
|
else
|
||||||
return L"";
|
return L"";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<wstring> StringHelper::splitQuoted(const wstring& s, wchar_t splitChar, wchar_t quoteChar)
|
||||||
|
{
|
||||||
|
vector<wstring> result;
|
||||||
|
bool inQuotes = false;
|
||||||
|
wstring current;
|
||||||
|
for (size_t i = 0; i < s.length(); i++)
|
||||||
|
{
|
||||||
|
wchar_t c = s[i];
|
||||||
|
if (c == splitChar && !inQuotes)
|
||||||
|
{
|
||||||
|
if (current != L"")
|
||||||
|
{
|
||||||
|
result.push_back(current);
|
||||||
|
current = L"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == quoteChar)
|
||||||
|
{
|
||||||
|
inQuotes = !inQuotes;
|
||||||
|
if (inQuotes && i > 0 && s[i - 1] == quoteChar)
|
||||||
|
current += quoteChar;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current != L"")
|
||||||
|
result.push_back(current);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -35,4 +35,5 @@ public:
|
|||||||
static std::vector<std::wstring> split(const std::wstring& s, wchar_t splitChar, bool skipEmpty = true);
|
static std::vector<std::wstring> split(const std::wstring& s, wchar_t splitChar, bool skipEmpty = true);
|
||||||
static std::wstring join(const std::vector<std::wstring>& strings, const std::wstring& separator);
|
static std::wstring join(const std::vector<std::wstring>& strings, const std::wstring& separator);
|
||||||
static std::wstring getSystemErrorString(long status);
|
static std::wstring getSystemErrorString(long status);
|
||||||
|
static std::vector<std::wstring> splitQuoted(const std::wstring& s, wchar_t splitChar, wchar_t quoteChar = '"');
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,397 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 <wincrypt.h>
|
||||||
|
#include "StringHelper.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "VSTPluginLibrary.h"
|
||||||
|
#include "VSTPluginInstance.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#define equalizerApoVSTID CCONST('E', 'A', 'P', 'O');
|
||||||
|
|
||||||
|
static intptr_t callback(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt)
|
||||||
|
{
|
||||||
|
VSTPluginInstance* instance = effect != NULL ? (VSTPluginInstance*)effect->user : NULL;
|
||||||
|
#ifdef _DEBUG
|
||||||
|
printf("vst: %p opcode: %d index: %d value: %d ptr: %p opt: %f user: %p\n",
|
||||||
|
effect, opcode, index, value, ptr, opt, effect != NULL ? effect->user : NULL);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (opcode)
|
||||||
|
{
|
||||||
|
case audioMasterVersion:
|
||||||
|
return 2400;
|
||||||
|
|
||||||
|
case audioMasterCurrentId:
|
||||||
|
return equalizerApoVSTID;
|
||||||
|
|
||||||
|
case audioMasterGetProductString:
|
||||||
|
strcpy_s((char*) ptr, 64, "Equalizer APO");
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case audioMasterGetVendorVersion:
|
||||||
|
return (intptr_t) (MAJOR << 24 | MINOR << 16 | REVISION << 8 | 0);
|
||||||
|
|
||||||
|
case audioMasterPinConnected:
|
||||||
|
if (instance != NULL)
|
||||||
|
return index < instance->getUsedChannelCount() ? 0 : 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterNeedIdle:
|
||||||
|
return effect->dispatcher(effect, effIdle, 0, 0, NULL, 0.0f);
|
||||||
|
|
||||||
|
case audioMasterUpdateDisplay:
|
||||||
|
return effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);
|
||||||
|
|
||||||
|
case audioMasterGetTime:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetSampleRate:
|
||||||
|
if (instance != NULL)
|
||||||
|
return (intptr_t)instance->getSampleRate();
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetCurrentProcessLevel:
|
||||||
|
if (instance != NULL)
|
||||||
|
return instance->getProcessLevel();
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetLanguage:
|
||||||
|
if (instance != NULL)
|
||||||
|
return instance->getLanguage();
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterWillReplaceOrAccumulate:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case audioMasterSizeWindow:
|
||||||
|
if (instance != NULL)
|
||||||
|
instance->onSizeWindow((int)index, (int)value);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case audioMasterCanDo:
|
||||||
|
{
|
||||||
|
char* s = (char*)ptr;
|
||||||
|
#ifdef _DEBUG
|
||||||
|
printf("VST canDo: %s\n", s);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
if (strcmp(s, "startStopProcess") == 0 ||
|
||||||
|
strcmp(s, "sizeWindow") == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterAutomate:
|
||||||
|
if (instance != NULL)
|
||||||
|
instance->onAutomate();
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterBeginEdit:
|
||||||
|
case audioMasterEndEdit:
|
||||||
|
case audioMasterIdle:
|
||||||
|
case audioMasterWantMidi:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
VSTPluginInstance::VSTPluginInstance(const std::shared_ptr<VSTPluginLibrary>& library, int processLevel)
|
||||||
|
: library(library), processLevel(processLevel)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VSTPluginInstance::~VSTPluginInstance()
|
||||||
|
{
|
||||||
|
if (effect != NULL)
|
||||||
|
{
|
||||||
|
effect->dispatcher(effect, effClose, 0, 0, NULL, 0.0f);
|
||||||
|
effect = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VSTPluginInstance::initialize()
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
effect = library->VSTPluginMain(callback);
|
||||||
|
effect->user = this;
|
||||||
|
if (effect->magic == kEffectMagic)
|
||||||
|
{
|
||||||
|
effect->dispatcher(effect, effOpen, 0, 0, NULL, 0.0f);
|
||||||
|
|
||||||
|
usedChannelCount = max(numInputs(), numOutputs());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
effect = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int VSTPluginInstance::numInputs() const
|
||||||
|
{
|
||||||
|
if (effect == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return effect->numInputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int VSTPluginInstance::numOutputs() const
|
||||||
|
{
|
||||||
|
if (effect == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return effect->numOutputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VSTPluginInstance::canReplacing() const
|
||||||
|
{
|
||||||
|
if (effect == NULL)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return (effect->flags & effFlagsCanReplacing) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int VSTPluginInstance::uniqueID() const
|
||||||
|
{
|
||||||
|
if (effect == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return effect->uniqueID;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring VSTPluginInstance::getName() const
|
||||||
|
{
|
||||||
|
if (effect == NULL)
|
||||||
|
return L"";
|
||||||
|
|
||||||
|
char buf[256];
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
effect->dispatcher(effect, effGetEffectName, 0, 0, buf, 0.0f);
|
||||||
|
|
||||||
|
return StringHelper::toWString(buf, CP_UTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
int VSTPluginInstance::getUsedChannelCount() const
|
||||||
|
{
|
||||||
|
return usedChannelCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::setUsedChannelCount(int count)
|
||||||
|
{
|
||||||
|
usedChannelCount = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
float VSTPluginInstance::getSampleRate() const
|
||||||
|
{
|
||||||
|
return sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
int VSTPluginInstance::getProcessLevel() const
|
||||||
|
{
|
||||||
|
return processLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::setProcessLevel(int value)
|
||||||
|
{
|
||||||
|
processLevel = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int VSTPluginInstance::getLanguage() const
|
||||||
|
{
|
||||||
|
return language;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::setLanguage(int value)
|
||||||
|
{
|
||||||
|
language = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::prepareForProcessing(float sampleRate, int blockSize)
|
||||||
|
{
|
||||||
|
if (effect == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this->sampleRate = sampleRate;
|
||||||
|
effect->dispatcher(effect, effSetSampleRate, 0, 0, NULL, sampleRate);
|
||||||
|
effect->dispatcher(effect, effSetBlockSize, 0, blockSize, NULL, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::writeToEffect(const std::wstring& chunkData, const std::unordered_map<std::wstring, float>& paramMap)
|
||||||
|
{
|
||||||
|
if (effect == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (effect->flags & effFlagsProgramChunks)
|
||||||
|
{
|
||||||
|
if (chunkData != L"")
|
||||||
|
{
|
||||||
|
DWORD bufSize = 0;
|
||||||
|
CryptStringToBinaryW(chunkData.c_str(), 0, CRYPT_STRING_BASE64, NULL, &bufSize, NULL, NULL);
|
||||||
|
BYTE* buf = new BYTE[bufSize];
|
||||||
|
if (CryptStringToBinaryW(chunkData.c_str(), 0, CRYPT_STRING_BASE64, buf, &bufSize, NULL, NULL) == TRUE)
|
||||||
|
effect->dispatcher(effect, effSetChunk, 1, bufSize, buf, 0.0f);
|
||||||
|
delete[]buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < effect->numParams; i++)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
effect->dispatcher(effect, effGetParamName, i, 0, buf, 0.0f);
|
||||||
|
wstring name = StringHelper::toWString(buf, CP_UTF8);
|
||||||
|
auto it = paramMap.find(name);
|
||||||
|
if (it != paramMap.end())
|
||||||
|
effect->setParameter(effect, i, it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::readFromEffect(std::wstring& chunkData, std::unordered_map<std::wstring, float>& paramMap) const
|
||||||
|
{
|
||||||
|
if (effect == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
chunkData = L"";
|
||||||
|
paramMap.clear();
|
||||||
|
|
||||||
|
if (effect->flags & effFlagsProgramChunks)
|
||||||
|
{
|
||||||
|
BYTE* chunk = NULL;
|
||||||
|
int size = (int)effect->dispatcher(effect, effGetChunk, 1, 0, &chunk, 0.0f);
|
||||||
|
DWORD stringLength;
|
||||||
|
CryptBinaryToStringW(chunk, size, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, &stringLength);
|
||||||
|
wchar_t* string = new wchar_t[stringLength];
|
||||||
|
if (CryptBinaryToStringW(chunk, size, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, string, &stringLength) == TRUE)
|
||||||
|
chunkData = string;
|
||||||
|
delete[]string;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < effect->numParams; i++)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
effect->dispatcher(effect, effGetParamName, i, 0, buf, 0.0f);
|
||||||
|
float value = effect->getParameter(effect, i);
|
||||||
|
paramMap[StringHelper::toWString(buf, CP_UTF8)] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::startProcessing()
|
||||||
|
{
|
||||||
|
if (effect == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
effect->dispatcher(effect, effMainsChanged, 0, 1, NULL, 0.0f);
|
||||||
|
effect->dispatcher(effect, effStartProcess, 0, 0, NULL, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::processReplacing(float** inputArray, float** outputArray, int frameCount)
|
||||||
|
{
|
||||||
|
if (effect == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
effect->processReplacing(effect, inputArray, outputArray, frameCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::process(float** inputArray, float** outputArray, int frameCount)
|
||||||
|
{
|
||||||
|
if (effect == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
effect->process(effect, inputArray, outputArray, frameCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::stopProcessing()
|
||||||
|
{
|
||||||
|
if (effect == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
effect->dispatcher(effect, effStopProcess, 0, 0, NULL, 0.0f);
|
||||||
|
effect->dispatcher(effect, effMainsChanged, 0, 0, NULL, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::startEditing(HWND hWnd, short* width, short* height)
|
||||||
|
{
|
||||||
|
if (effect == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
VstRect* rect;
|
||||||
|
effect->dispatcher(effect, effEditGetRect, 0, 0, &rect, 0.0f);
|
||||||
|
effect->dispatcher(effect, effEditOpen, 0, 0, hWnd, 0.0f);
|
||||||
|
effect->dispatcher(effect, effEditGetRect, 0, 0, &rect, 0.0f);
|
||||||
|
|
||||||
|
*width = rect->right - rect->left;
|
||||||
|
*height = rect->bottom - rect->top;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::doIdle()
|
||||||
|
{
|
||||||
|
if (effect == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::stopEditing()
|
||||||
|
{
|
||||||
|
if (effect == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
effect->dispatcher(effect, effEditClose, 0, 0, NULL, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::setAutomateFunc(std::function<void()> func)
|
||||||
|
{
|
||||||
|
automateFunc = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::onAutomate()
|
||||||
|
{
|
||||||
|
if (automateFunc)
|
||||||
|
automateFunc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::setSizeWindowFunc(std::function<void(int, int)> func)
|
||||||
|
{
|
||||||
|
sizeWindowFunc = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTPluginInstance::onSizeWindow(int w, int h)
|
||||||
|
{
|
||||||
|
if (sizeWindowFunc)
|
||||||
|
sizeWindowFunc(w, h);
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 <memory>
|
||||||
|
#include <functional>
|
||||||
|
#include "aeffectx.h"
|
||||||
|
|
||||||
|
class VSTPluginLibrary;
|
||||||
|
|
||||||
|
class VSTPluginInstance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VSTPluginInstance(const std::shared_ptr<VSTPluginLibrary>& library, int processLevel);
|
||||||
|
~VSTPluginInstance();
|
||||||
|
|
||||||
|
bool initialize();
|
||||||
|
|
||||||
|
int numInputs() const;
|
||||||
|
int numOutputs() const;
|
||||||
|
bool canReplacing() const;
|
||||||
|
int uniqueID() const;
|
||||||
|
std::wstring getName() const;
|
||||||
|
int getUsedChannelCount() const;
|
||||||
|
void setUsedChannelCount(int count);
|
||||||
|
float getSampleRate() const;
|
||||||
|
int getProcessLevel() const;
|
||||||
|
void setProcessLevel(int value);
|
||||||
|
int getLanguage() const;
|
||||||
|
void setLanguage(int value);
|
||||||
|
|
||||||
|
void prepareForProcessing(float sampleRate, int blockSize);
|
||||||
|
void writeToEffect(const std::wstring& chunkData, const std::unordered_map<std::wstring, float>& paramMap);
|
||||||
|
void readFromEffect(std::wstring& chunkData, std::unordered_map<std::wstring, float>& paramMap) const;
|
||||||
|
|
||||||
|
void startProcessing();
|
||||||
|
void processReplacing(float** inputArray, float** outputArray, int frameCount);
|
||||||
|
void process(float** inputArray, float** outputArray, int frameCount);
|
||||||
|
void stopProcessing();
|
||||||
|
|
||||||
|
void startEditing(HWND hWnd, short* width, short* height);
|
||||||
|
void doIdle();
|
||||||
|
void stopEditing();
|
||||||
|
|
||||||
|
void setAutomateFunc(std::function<void()> func);
|
||||||
|
void onAutomate();
|
||||||
|
|
||||||
|
void setSizeWindowFunc(std::function<void(int, int)> func);
|
||||||
|
void onSizeWindow(int w, int h);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<VSTPluginLibrary> library;
|
||||||
|
AEffect* effect;
|
||||||
|
std::function<void()> automateFunc;
|
||||||
|
std::function<void(int, int)> sizeWindowFunc;
|
||||||
|
float sampleRate = 0.0f;
|
||||||
|
int usedChannelCount;
|
||||||
|
int processLevel = 0;
|
||||||
|
int language = 1;
|
||||||
|
};
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 "RegistryHelper.h"
|
||||||
|
#include "LogHelper.h"
|
||||||
|
#include "VSTPluginLibrary.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
std::unordered_map<std::wstring, std::weak_ptr<VSTPluginLibrary> > VSTPluginLibrary::instanceMap;
|
||||||
|
std::wstring VSTPluginLibrary::defaultPluginPath;
|
||||||
|
|
||||||
|
std::shared_ptr<VSTPluginLibrary> VSTPluginLibrary::getInstance(const wstring& libPath)
|
||||||
|
{
|
||||||
|
shared_ptr<VSTPluginLibrary> ptr;
|
||||||
|
|
||||||
|
auto it = instanceMap.find(libPath);
|
||||||
|
if (it != instanceMap.end())
|
||||||
|
{
|
||||||
|
weak_ptr<VSTPluginLibrary> instance = it->second;
|
||||||
|
ptr = instance.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr == NULL)
|
||||||
|
{
|
||||||
|
ptr = shared_ptr<VSTPluginLibrary>(new VSTPluginLibrary(libPath));
|
||||||
|
instanceMap[libPath] = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
wstring VSTPluginLibrary::getDefaultPluginPath()
|
||||||
|
{
|
||||||
|
if (defaultPluginPath == L"")
|
||||||
|
{
|
||||||
|
wstring installPath = RegistryHelper::readValue(APP_REGPATH, L"InstallPath");
|
||||||
|
defaultPluginPath = installPath + L"\\plugins";
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultPluginPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring VSTPluginLibrary::getLibPath()
|
||||||
|
{
|
||||||
|
return libPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VSTPluginLibrary::loadFunctions()
|
||||||
|
{
|
||||||
|
VSTPluginMain = (vstPluginMain)GetProcAddress(module, "VSTPluginMain");
|
||||||
|
|
||||||
|
return VSTPluginMain != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
VSTPluginLibrary::VSTPluginLibrary(const wstring& libPath)
|
||||||
|
: libPath(libPath)
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Equalizer APO, 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 <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "AbstractLibrary.h"
|
||||||
|
#include "aeffectx.h"
|
||||||
|
#include <queue>
|
||||||
|
#include "VSTPluginInstance.h"
|
||||||
|
|
||||||
|
class VSTPluginLibrary : public AbstractLibrary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static std::shared_ptr<VSTPluginLibrary> getInstance(const std::wstring& libPath);
|
||||||
|
static std::wstring getDefaultPluginPath();
|
||||||
|
|
||||||
|
std::wstring getLibPath() override;
|
||||||
|
|
||||||
|
typedef AEffect* (* vstPluginMain)(audioMasterCallback audioMaster);
|
||||||
|
vstPluginMain VSTPluginMain;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool loadFunctions() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
VSTPluginLibrary(const std::wstring& libPath);
|
||||||
|
static std::unordered_map<std::wstring, std::weak_ptr<VSTPluginLibrary> > instanceMap;
|
||||||
|
static std::wstring defaultPluginPath;
|
||||||
|
std::wstring libPath;
|
||||||
|
};
|
||||||
@@ -0,0 +1,391 @@
|
|||||||
|
/*
|
||||||
|
* aeffectx.h - simple header to allow VeSTige compilation and eventually work
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||||
|
*
|
||||||
|
* 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 (see COPYING); if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _AEFFECTX_H
|
||||||
|
#define _AEFFECTX_H
|
||||||
|
|
||||||
|
#define CCONST(a, b, c, d)( ( ( (int) a ) << 24 ) | \
|
||||||
|
( ( (int) b ) << 16 ) | \
|
||||||
|
( ( (int) c ) << 8 ) | \
|
||||||
|
( ( (int) d ) << 0 ) )
|
||||||
|
|
||||||
|
const int audioMasterAutomate = 0;
|
||||||
|
const int audioMasterVersion = 1;
|
||||||
|
const int audioMasterCurrentId = 2;
|
||||||
|
const int audioMasterIdle = 3;
|
||||||
|
const int audioMasterPinConnected = 4;
|
||||||
|
// unsupported? 5
|
||||||
|
const int audioMasterWantMidi = 6;
|
||||||
|
const int audioMasterGetTime = 7;
|
||||||
|
const int audioMasterProcessEvents = 8;
|
||||||
|
const int audioMasterSetTime = 9;
|
||||||
|
const int audioMasterTempoAt = 10;
|
||||||
|
const int audioMasterGetNumAutomatableParameters = 11;
|
||||||
|
const int audioMasterGetParameterQuantization = 12;
|
||||||
|
const int audioMasterIOChanged = 13;
|
||||||
|
const int audioMasterNeedIdle = 14;
|
||||||
|
const int audioMasterSizeWindow = 15;
|
||||||
|
const int audioMasterGetSampleRate = 16;
|
||||||
|
const int audioMasterGetBlockSize = 17;
|
||||||
|
const int audioMasterGetInputLatency = 18;
|
||||||
|
const int audioMasterGetOutputLatency = 19;
|
||||||
|
const int audioMasterGetPreviousPlug = 20;
|
||||||
|
const int audioMasterGetNextPlug = 21;
|
||||||
|
const int audioMasterWillReplaceOrAccumulate = 22;
|
||||||
|
const int audioMasterGetCurrentProcessLevel = 23;
|
||||||
|
const int audioMasterGetAutomationState = 24;
|
||||||
|
const int audioMasterOfflineStart = 25;
|
||||||
|
const int audioMasterOfflineRead = 26;
|
||||||
|
const int audioMasterOfflineWrite = 27;
|
||||||
|
const int audioMasterOfflineGetCurrentPass = 28;
|
||||||
|
const int audioMasterOfflineGetCurrentMetaPass = 29;
|
||||||
|
const int audioMasterSetOutputSampleRate = 30;
|
||||||
|
// unsupported? 31
|
||||||
|
const int audioMasterGetSpeakerArrangement = 31; // deprecated in 2.4?
|
||||||
|
const int audioMasterGetVendorString = 32;
|
||||||
|
const int audioMasterGetProductString = 33;
|
||||||
|
const int audioMasterGetVendorVersion = 34;
|
||||||
|
const int audioMasterVendorSpecific = 35;
|
||||||
|
const int audioMasterSetIcon = 36;
|
||||||
|
const int audioMasterCanDo = 37;
|
||||||
|
const int audioMasterGetLanguage = 38;
|
||||||
|
const int audioMasterOpenWindow = 39;
|
||||||
|
const int audioMasterCloseWindow = 40;
|
||||||
|
const int audioMasterGetDirectory = 41;
|
||||||
|
const int audioMasterUpdateDisplay = 42;
|
||||||
|
const int audioMasterBeginEdit = 43;
|
||||||
|
const int audioMasterEndEdit = 44;
|
||||||
|
const int audioMasterOpenFileSelector = 45;
|
||||||
|
const int audioMasterCloseFileSelector = 46; // currently unused
|
||||||
|
const int audioMasterEditFile = 47; // currently unused
|
||||||
|
const int audioMasterGetChunkFile = 48; // currently unused
|
||||||
|
const int audioMasterGetInputSpeakerArrangement = 49; // currently unused
|
||||||
|
|
||||||
|
const int effFlagsHasEditor = 1;
|
||||||
|
const int effFlagsCanReplacing = 1 << 4; // very likely
|
||||||
|
const int effFlagsProgramChunks = 1 << 5; // from Ardour
|
||||||
|
const int effFlagsIsSynth = 1 << 8; // currently unused
|
||||||
|
|
||||||
|
const int effOpen = 0;
|
||||||
|
const int effClose = 1; // currently unused
|
||||||
|
const int effSetProgram = 2; // currently unused
|
||||||
|
const int effGetProgram = 3; // currently unused
|
||||||
|
// The next one was gleaned from http://www.kvraudio.com/forum/viewtopic.php?p=1905347
|
||||||
|
const int effSetProgramName = 4;
|
||||||
|
const int effGetProgramName = 5; // currently unused
|
||||||
|
// The next two were gleaned from http://www.kvraudio.com/forum/viewtopic.php?p=1905347
|
||||||
|
const int effGetParamLabel = 6;
|
||||||
|
const int effGetParamDisplay = 7;
|
||||||
|
const int effGetParamName = 8; // currently unused
|
||||||
|
const int effSetSampleRate = 10;
|
||||||
|
const int effSetBlockSize = 11;
|
||||||
|
const int effMainsChanged = 12;
|
||||||
|
const int effEditGetRect = 13;
|
||||||
|
const int effEditOpen = 14;
|
||||||
|
const int effEditClose = 15;
|
||||||
|
const int effEditIdle = 19;
|
||||||
|
const int effEditTop = 20;
|
||||||
|
const int effIdentify = 22; // from http://www.asseca.org/vst-24-specs/efIdentify.html
|
||||||
|
const int effGetChunk = 23; // from Ardour
|
||||||
|
const int effSetChunk = 24; // from Ardour
|
||||||
|
const int effProcessEvents = 25;
|
||||||
|
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efCanBeAutomated.html
|
||||||
|
const int effCanBeAutomated = 26;
|
||||||
|
// The next one was gleaned from http://www.kvraudio.com/forum/viewtopic.php?p=1905347
|
||||||
|
const int effGetProgramNameIndexed = 29;
|
||||||
|
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efGetPlugCategory.html
|
||||||
|
const int effGetPlugCategory = 35;
|
||||||
|
const int effGetEffectName = 45;
|
||||||
|
const int effGetParameterProperties = 56; // missing
|
||||||
|
const int effGetVendorString = 47;
|
||||||
|
const int effGetProductString = 48;
|
||||||
|
const int effGetVendorVersion = 49;
|
||||||
|
const int effCanDo = 51; // currently unused
|
||||||
|
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efIdle.html
|
||||||
|
const int effIdle = 53;
|
||||||
|
const int effGetVstVersion = 58; // currently unused
|
||||||
|
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efBeginSetProgram.html
|
||||||
|
const int effBeginSetProgram = 67;
|
||||||
|
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efEndSetProgram.html
|
||||||
|
const int effEndSetProgram = 68;
|
||||||
|
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efShellGetNextPlugin.html
|
||||||
|
const int effShellGetNextPlugin = 70;
|
||||||
|
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efBeginLoadBank.html
|
||||||
|
const int effBeginLoadBank = 75;
|
||||||
|
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efBeginLoadProgram.html
|
||||||
|
const int effBeginLoadProgram = 76;
|
||||||
|
|
||||||
|
// The next two were gleaned from http://www.kvraudio.com/forum/printview.php?t=143587&start=0
|
||||||
|
const int effStartProcess = 71;
|
||||||
|
const int effStopProcess = 72;
|
||||||
|
|
||||||
|
const int kEffectMagic = CCONST( 'V', 's', 't', 'P' );
|
||||||
|
const int kVstLangEnglish = 1;
|
||||||
|
const int kVstMidiType = 1;
|
||||||
|
|
||||||
|
const int kVstNanosValid = 1 << 8;
|
||||||
|
const int kVstPpqPosValid = 1 << 9;
|
||||||
|
const int kVstTempoValid = 1 << 10;
|
||||||
|
const int kVstBarsValid = 1 << 11;
|
||||||
|
const int kVstCyclePosValid = 1 << 12;
|
||||||
|
const int kVstTimeSigValid = 1 << 13;
|
||||||
|
const int kVstSmpteValid = 1 << 14; // from Ardour
|
||||||
|
const int kVstClockValid = 1 << 15; // from Ardour
|
||||||
|
|
||||||
|
const int kVstTransportPlaying = 1 << 1;
|
||||||
|
const int kVstTransportCycleActive = 1 << 2;
|
||||||
|
const int kVstTransportChanged = 1;
|
||||||
|
|
||||||
|
|
||||||
|
class RemoteVstPlugin;
|
||||||
|
|
||||||
|
|
||||||
|
class VstMidiEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// 00
|
||||||
|
int type;
|
||||||
|
// 04
|
||||||
|
int byteSize;
|
||||||
|
// 08
|
||||||
|
int deltaFrames;
|
||||||
|
// 0c?
|
||||||
|
int flags;
|
||||||
|
// 10?
|
||||||
|
int noteLength;
|
||||||
|
// 14?
|
||||||
|
int noteOffset;
|
||||||
|
// 18
|
||||||
|
char midiData[4];
|
||||||
|
// 1c?
|
||||||
|
char detune;
|
||||||
|
// 1d?
|
||||||
|
char noteOffVelocity;
|
||||||
|
// 1e?
|
||||||
|
char reserved1;
|
||||||
|
// 1f?
|
||||||
|
char reserved2;
|
||||||
|
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class VstEvent
|
||||||
|
{
|
||||||
|
char dump[sizeof( VstMidiEvent )];
|
||||||
|
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class VstEvents
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// 00
|
||||||
|
int numEvents;
|
||||||
|
// 04
|
||||||
|
void *reserved;
|
||||||
|
// 08
|
||||||
|
VstEvent* events[1];
|
||||||
|
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Not finished, neither really used
|
||||||
|
class VstParameterProperties
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/* float stepFloat;
|
||||||
|
char label[64];
|
||||||
|
int flags;
|
||||||
|
int minInteger;
|
||||||
|
int maxInteger;
|
||||||
|
int stepInteger;
|
||||||
|
char shortLabel[8];
|
||||||
|
int category;
|
||||||
|
char categoryLabel[24];
|
||||||
|
char empty[128];*/
|
||||||
|
|
||||||
|
float stepFloat;
|
||||||
|
float smallStepFloat;
|
||||||
|
float largeStepFloat;
|
||||||
|
char label[64];
|
||||||
|
unsigned int flags;
|
||||||
|
unsigned int minInteger;
|
||||||
|
unsigned int maxInteger;
|
||||||
|
unsigned int stepInteger;
|
||||||
|
unsigned int largeStepInteger;
|
||||||
|
char shortLabel[8];
|
||||||
|
unsigned short displayIndex;
|
||||||
|
unsigned short category;
|
||||||
|
unsigned short numParametersInCategory;
|
||||||
|
unsigned short reserved;
|
||||||
|
char categoryLabel[24];
|
||||||
|
char future[16];
|
||||||
|
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class AEffect
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Never use virtual functions!!!
|
||||||
|
// 00-03
|
||||||
|
int magic;
|
||||||
|
// dispatcher 04-07
|
||||||
|
intptr_t (* dispatcher)( AEffect * , int , int , intptr_t, void * , float );
|
||||||
|
// process, quite sure 08-0b
|
||||||
|
void (* process)( AEffect * , float * * , float * * , int );
|
||||||
|
// setParameter 0c-0f
|
||||||
|
void (* setParameter)( AEffect * , int , float );
|
||||||
|
// getParameter 10-13
|
||||||
|
float (* getParameter)( AEffect * , int );
|
||||||
|
// programs 14-17
|
||||||
|
int numPrograms;
|
||||||
|
// Params 18-1b
|
||||||
|
int numParams;
|
||||||
|
// Input 1c-1f
|
||||||
|
int numInputs;
|
||||||
|
// Output 20-23
|
||||||
|
int numOutputs;
|
||||||
|
// flags 24-27
|
||||||
|
int flags;
|
||||||
|
// Fill somewhere 28-2b
|
||||||
|
void * ptr1;
|
||||||
|
void * ptr2;
|
||||||
|
int initialDelay;
|
||||||
|
// Zeroes 34-37 38-3b
|
||||||
|
int empty3a;
|
||||||
|
int empty3b;
|
||||||
|
// 1.0f 3c-3f
|
||||||
|
float unkown_float;
|
||||||
|
// An object? pointer 40-43
|
||||||
|
void *ptr3;
|
||||||
|
// Zeroes 44-47
|
||||||
|
void *user;
|
||||||
|
// Id 48-4b
|
||||||
|
int32_t uniqueID;
|
||||||
|
int32_t version;
|
||||||
|
// processReplacing 50-53
|
||||||
|
void (* processReplacing)( AEffect * , float * * , float * * , int );
|
||||||
|
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class VstTimeInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// 00
|
||||||
|
double samplePos;
|
||||||
|
// 08
|
||||||
|
double sampleRate;
|
||||||
|
// 10
|
||||||
|
double nanoSeconds;
|
||||||
|
// 18
|
||||||
|
double ppqPos;
|
||||||
|
// 20?
|
||||||
|
double tempo;
|
||||||
|
// 28
|
||||||
|
double barStartPos;
|
||||||
|
// 30?
|
||||||
|
double cycleStartPos;
|
||||||
|
// 38?
|
||||||
|
double cycleEndPos;
|
||||||
|
// 40?
|
||||||
|
int timeSigNumerator;
|
||||||
|
// 44?
|
||||||
|
int timeSigDenominator;
|
||||||
|
// unconfirmed 48 4c 50
|
||||||
|
char empty3[4 + 4 + 4];
|
||||||
|
// 54
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef intptr_t (* audioMasterCallback)( AEffect * , int32_t, int32_t, intptr_t, void * , float );
|
||||||
|
|
||||||
|
|
||||||
|
// from http://www.asseca.org/vst-24-specs/efGetParameterProperties.html
|
||||||
|
enum VstParameterFlags
|
||||||
|
{
|
||||||
|
kVstParameterIsSwitch = 1 << 0, // parameter is a switch (on/off)
|
||||||
|
kVstParameterUsesIntegerMinMax = 1 << 1, // minInteger, maxInteger valid
|
||||||
|
kVstParameterUsesFloatStep = 1 << 2, // stepFloat, smallStepFloat, largeStepFloat valid
|
||||||
|
kVstParameterUsesIntStep = 1 << 3, // stepInteger, largeStepInteger valid
|
||||||
|
kVstParameterSupportsDisplayIndex = 1 << 4, // displayIndex valid
|
||||||
|
kVstParameterSupportsDisplayCategory = 1 << 5, // category, etc. valid
|
||||||
|
kVstParameterCanRamp = 1 << 6 // set if parameter value can ramp up/down
|
||||||
|
};
|
||||||
|
|
||||||
|
// from http://www.asseca.org/vst-24-specs/efBeginLoadProgram.html
|
||||||
|
struct VstPatchChunkInfo
|
||||||
|
{
|
||||||
|
int32_t version; // Format Version (should be 1)
|
||||||
|
int32_t pluginUniqueID; // UniqueID of the plug-in
|
||||||
|
int32_t pluginVersion; // Plug-in Version
|
||||||
|
int32_t numElements; // Number of Programs (Bank) or Parameters (Program)
|
||||||
|
char future[48]; // Reserved for future use
|
||||||
|
};
|
||||||
|
|
||||||
|
// from http://www.asseca.org/vst-24-specs/efGetPlugCategory.html
|
||||||
|
enum VstPlugCategory
|
||||||
|
{
|
||||||
|
kPlugCategUnknown = 0, // 0=Unknown, category not implemented
|
||||||
|
kPlugCategEffect, // 1=Simple Effect
|
||||||
|
kPlugCategSynth, // 2=VST Instrument (Synths, samplers,...)
|
||||||
|
kPlugCategAnalysis, // 3=Scope, Tuner, ...
|
||||||
|
kPlugCategMastering, // 4=Dynamics, ...
|
||||||
|
kPlugCategSpacializer, // 5=Panners, ...
|
||||||
|
kPlugCategRoomFx, // 6=Delays and Reverbs
|
||||||
|
kPlugSurroundFx, // 7=Dedicated surround processor
|
||||||
|
kPlugCategRestoration, // 8=Denoiser, ...
|
||||||
|
kPlugCategOfflineProcess, // 9=Offline Process
|
||||||
|
kPlugCategShell, // 10=Plug-in is container of other plug-ins @see effShellGetNextPlugin()
|
||||||
|
kPlugCategGenerator, // 11=ToneGenerator, ...
|
||||||
|
kPlugCategMaxCount // 12=Marker to count the categories
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class VstRect
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
short top;
|
||||||
|
short left;
|
||||||
|
short bottom;
|
||||||
|
short right;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in new issue
Block a user