vst3sdk-3.7.10.14+~4.13.3/ 0000775 0000000 0000000 00000000000 14615113443 0014350 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/CMakeLists.txt 0000664 0000000 0000000 00000015310 14615113443 0017110 0 ustar 00root root 0000000 0000000
cmake_minimum_required(VERSION 3.5.0)
project(smtg_public_sdk VERSION 1.0.0)
#--sdk common----------------
add_library(sdk_common
STATIC
source/common/commoniids.cpp
source/common/openurl.cpp
source/common/openurl.h
source/common/systemclipboard.h
source/common/systemclipboard_linux.cpp
source/common/systemclipboard_win32.cpp
source/common/threadchecker.h
source/common/threadchecker_linux.cpp
source/common/threadchecker_win32.cpp
)
if(VST_SDK)
target_sources(sdk_common
PRIVATE
source/common/readfile.cpp
source/common/readfile.h
source/vst/vstpresetfile.cpp
source/vst/vstpresetfile.h
)
else()
target_sources(sdk_common
PRIVATE
source/common/pvaluecontainer.cpp
source/common/pvaluecontainer.h
source/common/pattributes.cpp
source/common/pattributes.h
)
endif(VST_SDK)
if(SMTG_MAC)
target_sources(sdk_common
PRIVATE
source/common/threadchecker_mac.mm
source/common/systemclipboard_mac.mm
)
endif(SMTG_MAC)
# add dependencies
target_link_libraries(sdk_common
PUBLIC
base
pluginterfaces
)
target_include_directories(sdk_common
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/..
)
smtg_target_setup_universal_binary(sdk_common)
if(SMTG_MAC AND XCODE AND SMTG_ENABLE_IOS_TARGETS)
get_target_property(sdk_common_SOURCES sdk_common SOURCES)
add_library(sdk_common_ios
STATIC
${sdk_common_SOURCES}
)
smtg_target_set_platform_ios(sdk_common_ios)
set_target_properties(sdk_common_ios
PROPERTIES
${SDK_IDE_LIBS_FOLDER}
)
target_link_libraries(sdk_common_ios
PUBLIC
base_ios
pluginterfaces_ios
)
target_compile_features(sdk_common_ios PUBLIC cxx_std_17)
endif()
#--sdk plugin----------------
add_library(sdk
STATIC
source/common/pluginview.cpp
source/common/pluginview.h
source/main/pluginfactory.cpp
source/main/pluginfactory.h
source/main/pluginfactory_constexpr.h
)
# Additional sources for VST3 SDK usage
if(VST_SDK)
target_sources(sdk
PRIVATE
source/main/moduleinit.cpp
source/main/moduleinit.h
source/vst/utility/alignedalloc.h
source/vst/utility/audiobuffers.h
source/vst/utility/dataexchange.cpp
source/vst/utility/dataexchange.h
source/vst/utility/memoryibstream.h
source/vst/utility/processcontextrequirements.h
source/vst/utility/processdataslicer.h
source/vst/utility/ringbuffer.h
source/vst/utility/rttransfer.h
source/vst/utility/sampleaccurate.h
source/vst/utility/stringconvert.cpp
source/vst/utility/stringconvert.h
source/vst/utility/systemtime.h
source/vst/utility/systemtime.cpp
source/vst/utility/testing.cpp
source/vst/utility/testing.h
source/vst/utility/vst2persistence.h
source/vst/utility/vst2persistence.cpp
source/vst/vstaudioeffect.cpp
source/vst/vstaudioeffect.h
source/vst/vstbus.cpp
source/vst/vstbus.h
source/vst/vstbypassprocessor.h
source/vst/vstcomponent.cpp
source/vst/vstcomponent.h
source/vst/vstcomponentbase.cpp
source/vst/vstcomponentbase.h
source/vst/vsteditcontroller.cpp
source/vst/vsteditcontroller.h
source/vst/vsteventshelper.h
source/vst/vsthelpers.h
source/vst/vstinitiids.cpp
source/vst/vstnoteexpressiontypes.cpp
source/vst/vstnoteexpressiontypes.h
source/vst/vstparameters.cpp
source/vst/vstparameters.h
source/vst/vstrepresentation.cpp
source/vst/vstrepresentation.h
)
endif(VST_SDK)
target_compile_features(sdk
PUBLIC
cxx_std_17
)
# add dependencies
target_link_libraries(sdk
PUBLIC
sdk_common
)
target_include_directories(sdk
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/..
)
smtg_target_setup_universal_binary(sdk)
get_target_property(sdk_SOURCES sdk SOURCES)
# iOS target
if(SMTG_MAC AND XCODE AND SMTG_ENABLE_IOS_TARGETS)
add_library(sdk_ios
STATIC
${sdk_SOURCES}
)
smtg_target_set_platform_ios(sdk_ios)
set_target_properties(sdk_ios
PROPERTIES
${SDK_IDE_LIBS_FOLDER}
)
target_link_libraries(sdk_ios
PUBLIC
sdk_common_ios
)
target_compile_features(sdk_ios PUBLIC cxx_std_17)
endif(SMTG_MAC AND XCODE AND SMTG_ENABLE_IOS_TARGETS)
#--for hosting----------------
if(VST_SDK)
add_library(sdk_hosting
STATIC
source/vst/hosting/connectionproxy.cpp
source/vst/hosting/connectionproxy.h
source/vst/hosting/eventlist.cpp
source/vst/hosting/eventlist.h
source/vst/hosting/hostclasses.cpp
source/vst/hosting/hostclasses.h
source/vst/hosting/module.cpp
source/vst/hosting/module.h
source/vst/hosting/parameterchanges.cpp
source/vst/hosting/parameterchanges.h
source/vst/hosting/pluginterfacesupport.cpp
source/vst/hosting/pluginterfacesupport.h
source/vst/hosting/processdata.cpp
source/vst/hosting/processdata.h
source/vst/utility/optional.h
source/vst/utility/stringconvert.cpp
source/vst/utility/stringconvert.h
source/vst/utility/uid.h
source/vst/utility/versionparser.h
source/vst/vstinitiids.cpp
)
# add dependencies
target_link_libraries(sdk_hosting
PUBLIC
sdk_common
)
target_include_directories(sdk_hosting
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/..
)
smtg_target_setup_universal_binary(sdk_hosting)
# iOS target for hosting
if(SMTG_MAC AND XCODE AND SMTG_ENABLE_IOS_TARGETS)
get_target_property(sdk_hosting_SOURCES sdk_hosting SOURCES)
add_library(sdk_hosting_ios STATIC
${sdk_hosting_SOURCES}
)
smtg_target_set_platform_ios(sdk_hosting_ios)
set_target_properties(sdk_hosting_ios
PROPERTIES
${SDK_IDE_LIBS_FOLDER}
)
target_link_libraries(sdk_hosting_ios
PUBLIC
sdk_common_ios
)
target_compile_features(sdk_hosting_ios PUBLIC cxx_std_17)
target_include_directories(sdk_hosting_ios
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/..
)
endif(SMTG_MAC AND XCODE AND SMTG_ENABLE_IOS_TARGETS)
endif(VST_SDK)
vst3sdk-3.7.10.14+~4.13.3/LICENSE.txt 0000664 0000000 0000000 00000003500 14615113443 0016171 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
vst3sdk-3.7.10.14+~4.13.3/README.md 0000664 0000000 0000000 00000000735 14615113443 0015634 0 ustar 00root root 0000000 0000000 # Welcome to VST 3 SDK public_sdk
Here are located:
- helper classes implementing **VST 3** Interfaces
- samples of **VST 3** Hosting and **VST 3** plug-ins
- **AAX** Wrapper
- **AU** Wrapper
- **AUv3** Wrapper
- **VST 2** Wrapper
- InterAppAudio
## License & Usage guidelines
More details are found at [VST 3 SDK public_sdk License](https://forums.steinberg.net/t/vst-3-sdk-public-sdk-license/695592)
----
Return to [VST 3 SDK](https://github.com/steinbergmedia/vst3sdk)
vst3sdk-3.7.10.14+~4.13.3/samples/ 0000775 0000000 0000000 00000000000 14615113443 0016014 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/ 0000775 0000000 0000000 00000000000 14615113443 0020301 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/CMakeLists.txt 0000664 0000000 0000000 00000000145 14615113443 0023041 0 ustar 00root root 0000000 0000000
if(ANDROID)
return()
endif(ANDROID)
include(SMTG_AddSubDirectories)
smtg_add_subdirectories()
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/ 0000775 0000000 0000000 00000000000 14615113443 0022300 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/CMakeLists.txt 0000664 0000000 0000000 00000010425 14615113443 0025042 0 ustar 00root root 0000000 0000000
if(SMTG_ENABLE_VST3_HOSTING_EXAMPLES)
include(SMTG_FindJack)
if(${LIBJACK_FOUND})
set(audiohost_sources
"${SDK_ROOT}/public.sdk/samples/vst-hosting/editorhost/source/platform/iapplication.h"
"${SDK_ROOT}/public.sdk/source/vst/hosting/connectionproxy.cpp"
"${SDK_ROOT}/public.sdk/source/vst/hosting/connectionproxy.h"
"${SDK_ROOT}/public.sdk/source/vst/hosting/eventlist.cpp"
"${SDK_ROOT}/public.sdk/source/vst/hosting/eventlist.h"
"${SDK_ROOT}/public.sdk/source/vst/hosting/hostclasses.cpp"
"${SDK_ROOT}/public.sdk/source/vst/hosting/hostclasses.h"
"${SDK_ROOT}/public.sdk/source/vst/hosting/module.cpp"
"${SDK_ROOT}/public.sdk/source/vst/hosting/module.h"
"${SDK_ROOT}/public.sdk/source/vst/hosting/parameterchanges.cpp"
"${SDK_ROOT}/public.sdk/source/vst/hosting/parameterchanges.h"
"${SDK_ROOT}/public.sdk/source/vst/hosting/pluginterfacesupport.cpp"
"${SDK_ROOT}/public.sdk/source/vst/hosting/pluginterfacesupport.h"
"${SDK_ROOT}/public.sdk/source/vst/hosting/plugprovider.cpp"
"${SDK_ROOT}/public.sdk/source/vst/hosting/plugprovider.h"
"${SDK_ROOT}/public.sdk/source/vst/hosting/processdata.cpp"
"${SDK_ROOT}/public.sdk/source/vst/hosting/processdata.h"
"${SDK_ROOT}/public.sdk/source/vst/utility/optional.h"
"${SDK_ROOT}/public.sdk/source/vst/utility/stringconvert.cpp"
"${SDK_ROOT}/public.sdk/source/vst/utility/stringconvert.h"
"${SDK_ROOT}/public.sdk/source/vst/utility/uid.h"
"${SDK_ROOT}/public.sdk/source/vst/vstinitiids.cpp"
source/audiohost.cpp
source/audiohost.h
source/media/audioclient.cpp
source/media/audioclient.h
source/media/imediaserver.h
source/media/iparameterclient.h
source/media/jack/jackclient.cpp
source/media/miditovst.h
source/platform/appinit.h
source/usediids.cpp
)
if(SMTG_MAC)
set(audiohost_sources
${audiohost_sources}
"${SDK_ROOT}/public.sdk/source/vst/hosting/module_mac.mm"
)
set_source_files_properties(
"${SDK_ROOT}/public.sdk/source/vst/hosting/module_mac.mm" PROPERTIES
COMPILE_FLAGS "-fobjc-arc"
)
set(audiohost_PLATFORM_LIBS "-framework CoreFoundation")
get_filename_component(InfoPlistFile "resource/Info.plist" ABSOLUTE)
set(APP_PROPERTIES
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_INFO_PLIST ${InfoPlistFile}
)
elseif(SMTG_LINUX)
set(audiohost_sources
${audiohost_sources}
"${SDK_ROOT}/public.sdk/source/vst/hosting/module_linux.cpp"
)
set(audiohost_PLATFORM_LIBS)
set(APP_PROPERTIES)
elseif(SMTG_WIN)
set(audiohost_sources
${audiohost_sources}
"${SDK_ROOT}/public.sdk/source/vst/hosting/module_win32.cpp"
)
set(audiohost_PLATFORM_LIBS)
if(MSVC)
set(APP_PROPERTIES
LINK_FLAGS
"/SUBSYSTEM:console"
)
endif(MSVC)
endif(SMTG_MAC)
set(target audiohost)
add_executable(${target} ${audiohost_sources})
set_target_properties(${target}
PROPERTIES
${SDK_IDE_HOSTING_EXAMPLES_FOLDER}
)
target_compile_features(${target}
PUBLIC
cxx_std_17
)
target_link_libraries(${target}
PRIVATE
base sdk
${audiohost_PLATFORM_LIBS}
${LIBJACK_LIBRARY}
)
target_include_directories(${target}
PRIVATE
${LIBJACK_INCLUDE_DIR}
)
if (APP_PROPERTIES)
set_target_properties(${target}
PROPERTIES
${APP_PROPERTIES}
)
endif(APP_PROPERTIES)
else()
message(STATUS "[SMTG] LIBJACK_FOUND is not set.")
endif(${LIBJACK_FOUND})
endif(SMTG_ENABLE_VST3_HOSTING_EXAMPLES)
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/resource/ 0000775 0000000 0000000 00000000000 14615113443 0024127 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/resource/Info.plist 0000664 0000000 0000000 00000003107 14615113443 0026100 0 ustar 00root root 0000000 0000000
CFBundleDevelopmentRegion
en
CFBundleExecutable
audiohost
CFBundleIdentifier
com.steinberg.vstsdk.audiohost
CFBundleInfoDictionaryVersion
6.0
CFBundleName
audiohost
CFBundlePackageType
BNDL
CFBundleShortVersionString
1.0.0
CFBundleVersion
1
NSHumanReadableCopyright
Copyright © 2024 Steinberg. All rights reserved.
NSPrincipalClass
NSApplication
CFBundleDocumentTypes
CFBundleTypeExtensions
vst3
CFBundleTypeName
VST3 Plug-In
CFBundleTypeRole
Audio
UTImportedTypeDeclarations
UTTypeConformsTo
public.data
public.content
UTTypeDescription
VST3 Plug-In
UTTypeIdentifier
com.steinberg.vst3.plugin
UTTypeTagSpecification
public.filename-extension
vst3
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/source/ 0000775 0000000 0000000 00000000000 14615113443 0023600 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/source/audiohost.cpp 0000664 0000000 0000000 00000013535 14615113443 0026312 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Project : VST SDK
//
// Category : AudioHost
// Filename : public.sdk/samples/vst-hosting/audiohost/source/audiohost.cpp
// Created by : Steinberg 09.2016
// Description : Audio Host Example for VST 3
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#include "public.sdk/samples/vst-hosting/audiohost/source/audiohost.h"
#include "public.sdk/samples/vst-hosting/audiohost/source/platform/appinit.h"
#include "public.sdk/source/vst/hosting/hostclasses.h"
#include "public.sdk/source/vst/utility/stringconvert.h"
#include "base/source/fcommandline.h"
#include "pluginterfaces/base/funknown.h"
#include "pluginterfaces/base/fstrdefs.h"
#include "pluginterfaces/gui/iplugview.h"
#include "pluginterfaces/gui/iplugviewcontentscalesupport.h"
#include "pluginterfaces/vst/ivstaudioprocessor.h"
#include "pluginterfaces/vst/ivsteditcontroller.h"
#include "pluginterfaces/vst/vsttypes.h"
#include
#include
#if WIN32
#include "windows.h"
#include
#endif
//------------------------------------------------------------------------
namespace Steinberg {
FUnknown* gStandardPluginContext = new Vst::HostApplication ();
namespace Vst {
namespace AudioHost {
static AudioHost::AppInit gInit (std::make_unique ());
//------------------------------------------------------------------------
App::~App () noexcept
{
}
//------------------------------------------------------------------------
void App::startAudioClient (const std::string& path, VST3::Optional effectID,
uint32 flags)
{
std::string error;
module = VST3::Hosting::Module::create (path, error);
if (!module)
{
std::string reason = "Could not create Module for file:";
reason += path;
reason += "\nError: ";
reason += error;
// EditorHost::IPlatform::instance ().kill (-1, reason);
return;
}
auto factory = module->getFactory ();
for (auto& classInfo : factory.classInfos ())
{
if (classInfo.category () == kVstAudioEffectClass)
{
if (effectID)
{
if (*effectID != classInfo.ID ())
continue;
}
plugProvider = owned (new PlugProvider (factory, classInfo, true));
break;
}
}
if (!plugProvider)
{
std::string error;
if (effectID)
error =
"No VST3 Audio Module Class with UID " + effectID->toString () + " found in file ";
else
error = "No VST3 Audio Module Class found in file ";
error += path;
// EditorHost::IPlatform::instance ().kill (-1, error);
return;
}
OPtr component = plugProvider->getComponent ();
OPtr controller = plugProvider->getController ();
FUnknownPtr midiMapping (controller);
//! TODO: Query the plugProvider for a proper name which gets displayed in JACK.
vst3Processor = AudioClient::create ("VST 3 SDK", component, midiMapping);
}
//------------------------------------------------------------------------
void App::init (const std::vector& cmdArgs)
{
if (cmdArgs.empty ())
{
/*auto helpText = R"(
usage: AudioHost pluginPath
)";
*/
return;
}
VST3::Optional uid;
uint32 flags {};
startAudioClient (cmdArgs.back (), std::move (uid), flags);
}
//------------------------------------------------------------------------
void App::terminate ()
{
}
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
//------------------------------------------------------------------------
#if WIN32
int wmain (int argc, wchar_t* argv[])
{
std::vector cmdArgs;
for (int i = 1; i < argc; ++i)
cmdArgs.push_back (VST3::StringConvert::convert (Steinberg::wscast (argv[i])));
Steinberg::Vst::AudioHost::gInit.app->init (cmdArgs);
std::cout << "Press to continue . . .";
std::getchar ();
return 0;
}
#else
int main (int argc, char* argv[])
{
std::vector cmdArgs;
for (int i = 1; i < argc; ++i)
cmdArgs.push_back (argv[i]);
Steinberg::Vst::AudioHost::gInit.app->init (cmdArgs);
std::cout << "Press to continue . . .";
std::getchar ();
return 0;
}
#endif
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/source/audiohost.h 0000664 0000000 0000000 00000006335 14615113443 0025757 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : AudioHost
// Filename : public.sdk/samples/vst-hosting/audiohost/source/audiohost.h
// Created by : Steinberg 09.2016
// Description : Audio Host Example for VST 3
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/iapplication.h"
#include "public.sdk/samples/vst-hosting/audiohost/source/media/audioclient.h"
#include "public.sdk/source/vst/hosting/module.h"
#include "public.sdk/source/vst/hosting/plugprovider.h"
#include "public.sdk/source/vst/utility/optional.h"
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace AudioHost {
//------------------------------------------------------------------------
class App : public EditorHost::IApplication
{
public:
~App () noexcept override;
void init (const std::vector& cmdArgs) override;
void terminate () override;
private:
enum OpenFlags
{
};
void startAudioClient (const std::string& path, VST3::Optional effectID,
uint32 flags);
VST3::Hosting::Module::Ptr module {nullptr};
IPtr plugProvider {nullptr};
AudioClientPtr vst3Processor;
};
//------------------------------------------------------------------------
} // AudioHost
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/source/media/ 0000775 0000000 0000000 00000000000 14615113443 0024657 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/source/media/audioclient.cpp 0000664 0000000 0000000 00000033102 14615113443 0027662 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : AudioHost
// Filename : public.sdk/samples/vst-hosting/audiohost/source/media/audioclient.cpp
// Created by : Steinberg 09.2016
// Description : Audio Host Example for VST 3
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#include "audioclient.h"
#include "miditovst.h"
#include "public.sdk/source/vst/hosting/eventlist.h"
#include "public.sdk/source/vst/hosting/parameterchanges.h"
#include "public.sdk/source/vst/utility/stringconvert.h"
#include "pluginterfaces/vst/ivsteditcontroller.h"
#include "pluginterfaces/vst/ivstmidicontrollers.h"
#include
#include
#include
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
//------------------------------------------------------------------------
// From Vst2Wrapper
static MidiCCMapping initMidiCtrlerAssignment (IComponent* component, IMidiMapping* midiMapping)
{
MidiCCMapping midiCCMapping {};
if (!midiMapping || !component)
return midiCCMapping;
int32 busses = std::min (component->getBusCount (kEvent, kInput), kMaxMidiMappingBusses);
if (midiCCMapping[0][0].empty ())
{
for (int32 b = 0; b < busses; b++)
for (int32 i = 0; i < kMaxMidiChannels; i++)
midiCCMapping[b][i].resize (Vst::kCountCtrlNumber);
}
ParamID paramID;
for (int32 b = 0; b < busses; b++)
{
for (int16 ch = 0; ch < kMaxMidiChannels; ch++)
{
for (int32 i = 0; i < Vst::kCountCtrlNumber; i++)
{
paramID = kNoParamId;
if (midiMapping->getMidiControllerAssignment (b, ch, (CtrlNumber)i, paramID) ==
kResultTrue)
{
// TODO check if tag is associated to a parameter
midiCCMapping[b][ch][i] = paramID;
}
else
midiCCMapping[b][ch][i] = kNoParamId;
}
}
}
return midiCCMapping;
}
//------------------------------------------------------------------------
static void assignBusBuffers (const IAudioClient::Buffers& buffers, HostProcessData& processData,
bool unassign = false)
{
// Set outputs
auto bufferIndex = 0;
for (auto busIndex = 0; busIndex < processData.numOutputs; busIndex++)
{
auto channelCount = processData.outputs[busIndex].numChannels;
for (auto chanIndex = 0; chanIndex < channelCount; chanIndex++)
{
if (bufferIndex < buffers.numOutputs)
{
processData.setChannelBuffer (BusDirections::kOutput, busIndex, chanIndex,
unassign ? nullptr : buffers.outputs[bufferIndex]);
bufferIndex++;
}
}
}
// Set inputs
bufferIndex = 0;
for (auto busIndex = 0; busIndex < processData.numInputs; busIndex++)
{
auto channelCount = processData.inputs[busIndex].numChannels;
for (auto chanIndex = 0; chanIndex < channelCount; chanIndex++)
{
if (bufferIndex < buffers.numInputs)
{
processData.setChannelBuffer (BusDirections::kInput, busIndex, chanIndex,
unassign ? nullptr : buffers.inputs[bufferIndex]);
bufferIndex++;
}
}
}
}
//------------------------------------------------------------------------
static void unassignBusBuffers (const IAudioClient::Buffers& buffers, HostProcessData& processData)
{
assignBusBuffers (buffers, processData, true);
}
//------------------------------------------------------------------------
// Vst3Processor
//------------------------------------------------------------------------
AudioClient::AudioClient ()
{
}
//------------------------------------------------------------------------
AudioClient::~AudioClient ()
{
terminate ();
}
//------------------------------------------------------------------------
AudioClientPtr AudioClient::create (const Name& name, IComponent* component,
IMidiMapping* midiMapping)
{
auto newProcessor = std::make_shared ();
newProcessor->initialize (name, component, midiMapping);
return newProcessor;
}
//------------------------------------------------------------------------
void AudioClient::initProcessContext ()
{
processContext = {};
processContext.tempo = 120;
}
//------------------------------------------------------------------------
void AudioClient::createLocalMediaServer (const Name& name)
{
mediaServer = createMediaServer (name);
mediaServer->registerAudioClient (this);
mediaServer->registerMidiClient (this);
}
//------------------------------------------------------------------------
bool AudioClient::initialize (const Name& name, IComponent* _component, IMidiMapping* midiMapping)
{
component = _component;
if (!component)
return false;
initProcessData ();
paramTransferrer.setMaxParameters (1000);
if (midiMapping)
midiCCMapping = initMidiCtrlerAssignment (component, midiMapping);
createLocalMediaServer (name);
return true;
}
//------------------------------------------------------------------------
void AudioClient::terminate ()
{
mediaServer = nullptr;
FUnknownPtr processor = component;
if (!processor)
return;
processor->setProcessing (false);
component->setActive (false);
}
//------------------------------------------------------------------------
void AudioClient::initProcessData ()
{
// processData.prepare will be done in setBlockSize
processData.inputEvents = &eventList;
processData.inputParameterChanges = &inputParameterChanges;
processData.processContext = &processContext;
initProcessContext ();
}
//------------------------------------------------------------------------
IMidiClient::IOSetup AudioClient::getMidiIOSetup () const
{
IMidiClient::IOSetup iosetup;
auto count = component->getBusCount (MediaTypes::kEvent, BusDirections::kInput);
for (int32_t i = 0; i < count; i++)
{
BusInfo info;
if (component->getBusInfo (MediaTypes::kEvent, BusDirections::kInput, i, info) != kResultOk)
continue;
auto busName = VST3::StringConvert::convert (info.name, 128);
iosetup.inputs.push_back (busName);
}
count = component->getBusCount (MediaTypes::kEvent, BusDirections::kOutput);
for (int32_t i = 0; i < count; i++)
{
BusInfo info;
if (component->getBusInfo (MediaTypes::kEvent, BusDirections::kOutput, i, info) !=
kResultOk)
continue;
auto busName = VST3::StringConvert::convert (info.name, 128);
iosetup.outputs.push_back (busName);
}
return iosetup;
}
//------------------------------------------------------------------------
IAudioClient::IOSetup AudioClient::getIOSetup () const
{
IAudioClient::IOSetup iosetup;
auto count = component->getBusCount (MediaTypes::kAudio, BusDirections::kOutput);
for (int32_t i = 0; i < count; i++)
{
BusInfo info;
if (component->getBusInfo (MediaTypes::kAudio, BusDirections::kOutput, i, info) !=
kResultOk)
continue;
for (int32_t j = 0; j < info.channelCount; j++)
{
auto channelName = VST3::StringConvert::convert (info.name, 128);
iosetup.outputs.push_back (channelName + " " + std::to_string (j));
}
}
count = component->getBusCount (MediaTypes::kAudio, BusDirections::kInput);
for (int32_t i = 0; i < count; i++)
{
BusInfo info;
if (component->getBusInfo (MediaTypes::kAudio, BusDirections::kInput, i, info) != kResultOk)
continue;
for (int32_t j = 0; j < info.channelCount; j++)
{
auto channelName = VST3::StringConvert::convert (info.name, 128);
iosetup.inputs.push_back (channelName + " " + std::to_string (j));
}
}
return iosetup;
}
//------------------------------------------------------------------------
void AudioClient::preprocess (Buffers& buffers, int64_t continousFrames)
{
processData.numSamples = buffers.numSamples;
processContext.continousTimeSamples = continousFrames;
assignBusBuffers (buffers, processData);
paramTransferrer.transferChangesTo (inputParameterChanges);
}
//------------------------------------------------------------------------
bool AudioClient::process (Buffers& buffers, int64_t continousFrames)
{
FUnknownPtr processor = component;
if (!processor || !isProcessing)
return false;
preprocess (buffers, continousFrames);
if (processor->process (processData) != kResultOk)
return false;
postprocess (buffers);
return true;
}
//------------------------------------------------------------------------
void AudioClient::postprocess (Buffers& buffers)
{
eventList.clear ();
inputParameterChanges.clearQueue ();
unassignBusBuffers (buffers, processData);
}
//------------------------------------------------------------------------
bool AudioClient::setSamplerate (SampleRate value)
{
if (sampleRate == value)
return true;
sampleRate = value;
processContext.sampleRate = sampleRate;
if (blockSize == 0)
return true;
return updateProcessSetup ();
}
//------------------------------------------------------------------------
bool AudioClient::setBlockSize (int32 value)
{
if (blockSize == value)
return true;
blockSize = value;
if (sampleRate == 0)
return true;
processData.prepare (*component, blockSize, kSample32);
return updateProcessSetup ();
}
//------------------------------------------------------------------------
bool AudioClient::updateProcessSetup ()
{
FUnknownPtr processor = component;
if (!processor)
return false;
if (isProcessing)
{
if (processor->setProcessing (false) != kResultOk)
return false;
if (component->setActive (false) != kResultOk)
return false;
}
ProcessSetup setup {kRealtime, kSample32, blockSize, sampleRate};
if (processor->setupProcessing (setup) != kResultOk)
return false;
if (component->setActive (true) != kResultOk)
return false;
processor->setProcessing (true); // != kResultOk
/*
if (processor->setProcessing(true) != kResultOk)
return false;*/
isProcessing = true;
return isProcessing;
}
//------------------------------------------------------------------------
bool AudioClient::isPortInRange (int32 port, int32 channel) const
{
return port < kMaxMidiMappingBusses && !midiCCMapping[port][channel].empty ();
}
//------------------------------------------------------------------------
bool AudioClient::processVstEvent (const IMidiClient::Event& event, int32 port)
{
auto vstEvent = midiToEvent (event.type, event.channel, event.data0, event.data1);
if (vstEvent)
{
vstEvent->busIndex = port;
if (eventList.addEvent (*vstEvent) != kResultOk)
{
assert (false && "Event was not added to EventList!");
}
return true;
}
return false;
}
//------------------------------------------------------------------------
bool AudioClient::processParamChange (const IMidiClient::Event& event, int32 port)
{
auto paramMapping = [port, this] (int32 channel, MidiData data1) -> ParamID {
if (!isPortInRange (port, channel))
return kNoParamId;
return midiCCMapping[port][channel][data1];
};
auto paramChange =
midiToParameter (event.type, event.channel, event.data0, event.data1, paramMapping);
if (paramChange)
{
int32 index = 0;
IParamValueQueue* queue =
inputParameterChanges.addParameterData ((*paramChange).first, index);
if (queue)
{
if (queue->addPoint (event.timestamp, (*paramChange).second, index) != kResultOk)
{
assert (false && "Parameter point was not added to ParamValueQueue!");
}
}
return true;
}
return false;
}
//------------------------------------------------------------------------
bool AudioClient::onEvent (const IMidiClient::Event& event, int32_t port)
{
// Try to create Event first.
if (processVstEvent (event, port))
return true;
// In case this is no event it must be a parameter.
if (processParamChange (event, port))
return true;
// TODO: Something else???
return true;
}
//------------------------------------------------------------------------
void AudioClient::setParameter (ParamID id, ParamValue value, int32 sampleOffset)
{
paramTransferrer.addChange (id, value, sampleOffset);
}
//------------------------------------------------------------------------
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/source/media/audioclient.h 0000664 0000000 0000000 00000012220 14615113443 0027325 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : AudioHost
// Filename : public.sdk/samples/vst-hosting/audiohost/source/audioclient.h
// Created by : Steinberg 09.2016
// Description : Audio Host Example for VST 3
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include "public.sdk/samples/vst-hosting/audiohost/source/media/imediaserver.h"
#include "public.sdk/samples/vst-hosting/audiohost/source/media/iparameterclient.h"
#include "public.sdk/source/vst/hosting/eventlist.h"
#include "public.sdk/source/vst/hosting/parameterchanges.h"
#include "public.sdk/source/vst/hosting/processdata.h"
#include "pluginterfaces/vst/ivstaudioprocessor.h"
#include
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
//------------------------------------------------------------------------
class IMidiMapping;
class IComponent;
enum
{
kMaxMidiMappingBusses = 4,
kMaxMidiChannels = 16
};
using Controllers = std::vector;
using Channels = std::array;
using Busses = std::array;
using MidiCCMapping = Busses;
//------------------------------------------------------------------------
using AudioClientPtr = std::shared_ptr;
//------------------------------------------------------------------------
class AudioClient : public IAudioClient, public IMidiClient, public IParameterClient
{
public:
//--------------------------------------------------------------------
using Name = std::string;
AudioClient ();
virtual ~AudioClient ();
static AudioClientPtr create (const Name& name, IComponent* component,
IMidiMapping* midiMapping);
// IAudioClient
bool process (Buffers& buffers, int64_t continousFrames) override;
bool setSamplerate (SampleRate value) override;
bool setBlockSize (int32 value) override;
IAudioClient::IOSetup getIOSetup () const override;
// IMidiClient
bool onEvent (const Event& event, int32_t port) override;
IMidiClient::IOSetup getMidiIOSetup () const override;
// IParameterClient
void setParameter (ParamID id, ParamValue value, int32 sampleOffset) override;
bool initialize (const Name& name, IComponent* component, IMidiMapping* midiMapping);
//--------------------------------------------------------------------
private:
void createLocalMediaServer (const Name& name);
void terminate ();
void updateBusBuffers (Buffers& buffers, HostProcessData& processData);
void initProcessData ();
void initProcessContext ();
bool updateProcessSetup ();
void preprocess (Buffers& buffers, int64_t continousFrames);
void postprocess (Buffers& buffers);
bool isPortInRange (int32 port, int32 channel) const;
bool processVstEvent (const IMidiClient::Event& event, int32 port);
bool processParamChange (const IMidiClient::Event& event, int32 port);
SampleRate sampleRate = 0;
int32 blockSize = 0;
HostProcessData processData;
ProcessContext processContext;
EventList eventList;
ParameterChanges inputParameterChanges;
IComponent* component = nullptr;
ParameterChangeTransfer paramTransferrer;
MidiCCMapping midiCCMapping;
IMediaServerPtr mediaServer;
bool isProcessing = false;
Name name;
};
//------------------------------------------------------------------------
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/source/media/imediaserver.h 0000664 0000000 0000000 00000007644 14615113443 0027522 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : AudioHost
// Filename : public.sdk/samples/vst-hosting/audiohost/source/media/imediaserver.h
// Created by : Steinberg 09.2016
// Description : Audio Host Example for VST 3
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include
#include
#include
#include
//----------------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
using IOName = std::string;
using IONames = std::vector;
using AudioClientName = std::string;
struct IAudioClient
{
struct Buffers
{
float** inputs;
int32_t numInputs;
float** outputs;
int32_t numOutputs;
int32_t numSamples;
};
struct IOSetup
{
IONames inputs;
IONames outputs;
};
virtual bool process (Buffers& buffers, int64_t continousFrames) = 0;
virtual bool setSamplerate (SampleRate value) = 0;
virtual bool setBlockSize (int32 value) = 0;
virtual IOSetup getIOSetup () const = 0;
virtual ~IAudioClient () {}
};
//----------------------------------------------------------------------------------
struct IMidiClient
{
using MidiData = uint8_t;
struct Event
{
MidiData type;
MidiData channel;
MidiData data0;
MidiData data1;
int64_t timestamp;
};
struct IOSetup
{
IONames inputs;
IONames outputs;
};
virtual bool onEvent (const Event& event, int32_t port) = 0;
virtual IOSetup getMidiIOSetup () const = 0;
virtual ~IMidiClient () {}
};
//----------------------------------------------------------------------------------
struct IMediaServer
{
virtual bool registerAudioClient (IAudioClient* client) = 0;
virtual bool registerMidiClient (IMidiClient* client) = 0;
virtual ~IMediaServer () {}
};
//----------------------------------------------------------------------------------
using IMediaServerPtr = std::shared_ptr;
IMediaServerPtr createMediaServer (const AudioClientName& name);
//----------------------------------------------------------------------------------
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/source/media/iparameterclient.h 0000664 0000000 0000000 00000005471 14615113443 0030367 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : AudioHost
// Filename : public.sdk/samples/vst-hosting/audiohost/source/media/iparameterclient.h
// Created by : Steinberg 09.2016
// Description : Audio Host Example for VST 3
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include
#include
//----------------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
//----------------------------------------------------------------------------------
struct IParameterClient
{
virtual void setParameter (ParamID id, ParamValue value, int32 sampleOffset) = 0;
virtual ~IParameterClient () {}
};
//----------------------------------------------------------------------------------
using IParameterClientPtr = std::weak_ptr;
//----------------------------------------------------------------------------------
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/source/media/jack/ 0000775 0000000 0000000 00000000000 14615113443 0025567 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/source/media/jack/jackclient.cpp 0000664 0000000 0000000 00000032011 14615113443 0030377 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : AudioHost
// Filename : public.sdk/samples/vst-hosting/audiohost/source/media/jack/jackclient.cpp
// Created by : Steinberg 09.2016
// Description : Audio Host Example for VST 3 using Jack
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#include "public.sdk/samples/vst-hosting/audiohost/source/media/imediaserver.h"
#include
//! Workaround for Jack on Windows
#if defined(SMTG_OS_WINDOWS) && defined(_STDINT)
#define _STDINT_H
#endif
#include
#include
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
static const int kJackSuccess = 0;
//------------------------------------------------------------------------
// jack Client
//------------------------------------------------------------------------
class JackClient : public IMediaServer
{
public:
//--------------------------------------------------------------------
using JackPorts = std::vector;
using JackName = std::string;
JackClient () = default;
virtual ~JackClient ();
// IMediaServer interface
bool registerAudioClient (IAudioClient* client) override;
bool registerMidiClient (IMidiClient* client) override;
bool initialize (JackName name);
// jack process callback
int process (jack_nframes_t nframes);
//--------------------------------------------------------------------
private:
jack_client_t* registerClient (JackName name);
bool registerAudioPorts (IAudioClient* processor);
bool registerMidiPorts (IMidiClient* processor);
bool addAudioOutputPort (JackName name);
bool addAudioInputPort (JackName name);
bool addMidiInputPort (JackName name);
int processMidi (jack_nframes_t nframes);
bool setupJackProcessCallbacks (jack_client_t* client);
bool autoConnectAudioPorts (jack_client_t* client);
bool autoConnectMidiPorts (jack_client_t* client);
void updateAudioBuffers (jack_nframes_t nframes);
// Jack objects
jack_client_t* jackClient = nullptr;
JackPorts audioOutputPorts;
JackPorts audioInputPorts;
JackPorts midiInputPorts;
IAudioClient* audioClient = nullptr;
IMidiClient* midiClient = nullptr;
using BufferPointers = std::vector;
BufferPointers audioOutputPointers;
BufferPointers audioInputPointers;
IAudioClient::Buffers buffers {nullptr};
};
//------------------------------------------------------------------------
int jack_on_process (jack_nframes_t nframes, void* arg)
{
auto client = reinterpret_cast (arg);
return client->process (nframes);
}
//------------------------------------------------------------------------
int jack_on_set_sample_rate (jack_nframes_t nframes, void* arg)
{
auto client = reinterpret_cast (arg);
client->setSamplerate (static_cast (nframes));
return kJackSuccess;
}
//------------------------------------------------------------------------
int jack_on_set_block_size (jack_nframes_t nframes, void* arg)
{
auto client = reinterpret_cast (arg);
client->setBlockSize (static_cast (nframes));
return kJackSuccess;
}
//------------------------------------------------------------------------
IMediaServerPtr createMediaServer (const AudioClientName& name)
{
auto client = std::make_shared ();
client->initialize (name);
return client;
}
//------------------------------------------------------------------------
JackClient::~JackClient ()
{
//! We do not need to "unregister" ports. It is done automatically with "jack_client_close"
jack_deactivate (jackClient); // Stops calls of process
jack_client_close (jackClient); // Remove client from process graph and remove all ports
}
//------------------------------------------------------------------------
bool JackClient::registerAudioClient (IAudioClient* client)
{
if (audioClient)
return false;
audioClient = client;
//! First thing to do: register the audio ports.
if (!registerAudioPorts (audioClient))
return false;
//! Setup all the callbacks like setSampleRate and process etc.
if (!setupJackProcessCallbacks (jackClient))
return false;
//! Activate after defining the callbacks. It is said in the documentation.
if (jack_activate (jackClient) != kJackSuccess)
return false;
//! AFTER activation, register the ports.
if (!autoConnectAudioPorts (jackClient))
return false;
return true;
}
//------------------------------------------------------------------------
bool JackClient::registerMidiClient (IMidiClient* client)
{
if (midiClient)
return false;
midiClient = client;
//! Register the midi ports.
if (!registerMidiPorts (midiClient))
return false;
//! Afterwards auto-connect them.
if (!autoConnectMidiPorts (jackClient))
return false;
return true;
}
//------------------------------------------------------------------------
bool JackClient::initialize (JackClient::JackName name)
{
jackClient = registerClient (name);
if (!jackClient)
return false;
return true;
}
//------------------------------------------------------------------------
void JackClient::updateAudioBuffers (jack_nframes_t nframes)
{
int outputIndex = 0;
for (auto audioOutputPort : audioOutputPorts)
{
auto* portBuffer = jack_port_get_buffer (audioOutputPort, nframes);
if (!portBuffer)
continue;
buffers.outputs[outputIndex++] = static_cast (portBuffer);
}
int inputIndex = 0;
for (auto audioInputPort : audioInputPorts)
{
auto* portBuffer = jack_port_get_buffer (audioInputPort, nframes);
if (!portBuffer)
continue;
buffers.inputs[inputIndex++] = static_cast (portBuffer);
}
}
//------------------------------------------------------------------------
int JackClient::process (jack_nframes_t nframes)
{
processMidi (nframes);
buffers.numSamples = nframes;
updateAudioBuffers (nframes);
if (!audioClient)
return 0;
if (audioClient->process (buffers, jack_last_frame_time (jackClient)) == false)
{
assert (false);
}
return kJackSuccess;
}
//------------------------------------------------------------------------
bool JackClient::registerAudioPorts (IAudioClient* processor)
{
auto ioSetup = processor->getIOSetup ();
for (const auto& output : ioSetup.outputs)
addAudioOutputPort (output);
for (const auto& input : ioSetup.inputs)
addAudioInputPort (input);
buffers.inputs = audioInputPointers.data ();
buffers.numInputs = (int32_t)audioInputPointers.size ();
buffers.numOutputs = (int32_t)audioOutputPointers.size ();
buffers.outputs = audioOutputPointers.data ();
return true;
}
//------------------------------------------------------------------------
bool JackClient::registerMidiPorts (IMidiClient* processor)
{
const auto ioSetup = processor->getMidiIOSetup ();
for (const auto& input : ioSetup.inputs)
addMidiInputPort (input);
return true;
}
//------------------------------------------------------------------------
bool JackClient::addAudioOutputPort (JackClient::JackName name)
{
auto port =
jack_port_register (jackClient, name.data (), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
if (!port)
return false;
audioOutputPorts.push_back (port);
audioOutputPointers.resize (audioOutputPorts.size ());
return true;
}
//------------------------------------------------------------------------
bool JackClient::addAudioInputPort (JackClient::JackName name)
{
auto port =
jack_port_register (jackClient, name.data (), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
if (!port)
return false;
audioInputPorts.push_back (port);
audioInputPointers.resize (audioOutputPorts.size ());
return true;
}
//------------------------------------------------------------------------
bool JackClient::addMidiInputPort (JackClient::JackName name)
{
auto port =
jack_port_register (jackClient, name.data (), JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
if (!port)
return false;
midiInputPorts.push_back (port);
return true;
}
//------------------------------------------------------------------------
int JackClient::processMidi (jack_nframes_t nframes)
{
static const uint8_t kChannelMask = 0x0F;
static const uint8_t kStatusMask = 0xF0;
static const uint32_t kDataMask = 0x7F;
for (int32_t portIndex = 0, count = static_cast (midiInputPorts.size ());
portIndex < count; ++portIndex)
{
auto midiInputPort = midiInputPorts.at (portIndex);
auto* portBuffer = jack_port_get_buffer (midiInputPort, nframes);
if (!portBuffer)
continue;
jack_midi_event_t in_event;
auto event_count = jack_midi_get_event_count (portBuffer);
for (uint32_t i = 0; i < event_count; i++)
{
jack_midi_event_get (&in_event, portBuffer, i);
if (in_event.size == 0)
continue;
auto midiData = in_event.buffer;
Steinberg::Vst::IMidiClient::MidiData channel = midiData[0] & kChannelMask;
Steinberg::Vst::IMidiClient::MidiData status = midiData[0] & kStatusMask;
Steinberg::Vst::IMidiClient::MidiData data0 = midiData[1];
Steinberg::Vst::IMidiClient::MidiData data1 = midiData[2];
midiClient->onEvent ({status, channel, data0, data1, in_event.time}, portIndex);
}
}
return kJackSuccess;
}
//------------------------------------------------------------------------
jack_client_t* JackClient::registerClient (JackClient::JackName name)
{
jack_options_t options = JackNullOption;
jack_status_t status;
jackClient = jack_client_open (name.data (), options, &status, nullptr);
return jackClient;
/* Use the status to check for errors:
if (status & JackServerFailed)
{
fprintf (stderr, "Unable to connect to JACK server\n");
}*/
}
//------------------------------------------------------------------------
bool JackClient::setupJackProcessCallbacks (jack_client_t* client)
{
if (jack_set_process_callback (client, jack_on_process, this) != kJackSuccess)
return false;
if (jack_set_sample_rate_callback (client, jack_on_set_sample_rate, audioClient) !=
kJackSuccess)
return false;
if (jack_set_buffer_size_callback (client, jack_on_set_block_size, audioClient) != kJackSuccess)
return false;
return true;
}
//------------------------------------------------------------------------
bool JackClient::autoConnectAudioPorts (jack_client_t* client)
{
int portIndex = 0;
//! Connect Audio Outputs
auto ports = jack_get_ports (client, nullptr, nullptr, JackPortIsPhysical | JackPortIsInput);
for (auto& port : audioOutputPorts)
{
if (!ports[portIndex])
break;
auto output__port_name = ports[portIndex++];
auto res = jack_connect (client, jack_port_name (port), output__port_name);
if (res != 0)
break;
}
jack_free (ports);
return true;
}
//------------------------------------------------------------------------
bool JackClient::autoConnectMidiPorts (jack_client_t* client)
{
int portIndex = 1;
//! Connect MIDI Inputs
auto ports = jack_get_ports (client, nullptr, "midi", JackPortIsPhysical | JackPortIsOutput);
if (!ports)
return false;
for (auto& port : midiInputPorts)
{
if (!ports[portIndex])
break;
auto inputPortName = ports[portIndex++];
auto res = jack_connect (client, inputPortName, jack_port_name (port));
if (res != 0)
continue;
}
jack_free (ports);
return true;
}
//------------------------------------------------------------------------
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/source/media/miditovst.h 0000664 0000000 0000000 00000013261 14615113443 0027055 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : AudioHost
// Filename : public.sdk/samples/vst-hosting/audiohost/source/media/miditovst.h
// Created by : Steinberg 09.2016
// Description : Audio Host Example for VST 3
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include "public.sdk/source/vst/utility/optional.h"
#include "pluginterfaces/vst/ivstevents.h"
#include "pluginterfaces/vst/ivstmidicontrollers.h"
#include
#include
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
const uint8_t kNoteOff = 0x80; ///< note, off velocity
const uint8_t kNoteOn = 0x90; ///< note, on velocity
const uint8_t kPolyPressure = 0xA0; ///< note, pressure
const uint8_t kController = 0xB0; ///< controller, value
const uint8_t kProgramChangeStatus = 0xC0; ///< program change
const uint8_t kAfterTouchStatus = 0xD0; ///< channel pressure
const uint8_t kPitchBendStatus = 0xE0; ///< lsb, msb
static const uint32 kDataMask = 0x7F;
const float kMidiScaler = 1.f / 127.f;
using MidiData = uint8_t;
float toNormalized (const MidiData& data)
{
return (float)data * kMidiScaler;
}
using OptionalEvent = VST3::Optional;
using ParameterChange = std::pair;
using OptionParamChange = VST3::Optional;
OptionalEvent midiToEvent (MidiData status, MidiData channel, MidiData midiData0,
MidiData midiData1)
{
Event new_event = {};
if (status == kNoteOn || status == kNoteOff)
{
if (status == kNoteOff) // note off
{
new_event.noteOff.noteId = -1;
new_event.type = Event::kNoteOffEvent;
new_event.noteOff.channel = channel;
new_event.noteOff.pitch = midiData0;
new_event.noteOff.velocity = toNormalized (midiData1);
return std::move (new_event);
}
else if (status == kNoteOn) // note on
{
new_event.noteOn.noteId = -1;
new_event.type = Event::kNoteOnEvent;
new_event.noteOn.channel = channel;
new_event.noteOn.pitch = midiData0;
new_event.noteOn.velocity = toNormalized (midiData1);
return std::move (new_event);
}
}
//--- -----------------------------
else if (status == kPolyPressure)
{
new_event.type = Vst::Event::kPolyPressureEvent;
new_event.polyPressure.channel = channel;
new_event.polyPressure.pitch = midiData0;
new_event.polyPressure.pressure = toNormalized (midiData1);
return std::move (new_event);
}
return {};
}
//------------------------------------------------------------------------
using ToParameterIdFunc = std::function;
OptionParamChange midiToParameter (MidiData status, MidiData channel, MidiData midiData1,
MidiData midiData2, const ToParameterIdFunc& toParamID)
{
if (!toParamID)
return {};
ParameterChange paramChange;
if (status == kController) // controller
{
paramChange.first = toParamID (channel, midiData1);
if (paramChange.first != kNoParamId)
{
paramChange.second = (double)midiData2 * kMidiScaler;
return std::move (paramChange);
}
}
else if (status == kPitchBendStatus)
{
paramChange.first = toParamID (channel, Vst::kPitchBend);
if (paramChange.first != kNoParamId)
{
const double kPitchWheelScaler = 1. / (double)0x3FFF;
const int32 ctrl = (midiData1 & kDataMask) | (midiData2 & kDataMask) << 7;
paramChange.second = kPitchWheelScaler * (double)ctrl;
return std::move (paramChange);
};
}
else if (status == kAfterTouchStatus)
{
paramChange.first = toParamID (channel, Vst::kAfterTouch);
if (paramChange.first != kNoParamId)
{
paramChange.second = (ParamValue) (midiData1 & kDataMask) * kMidiScaler;
return std::move (paramChange);
};
}
else if (status == kProgramChangeStatus)
{
// TODO
}
return {};
}
//------------------------------------------------------------------------
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/source/platform/ 0000775 0000000 0000000 00000000000 14615113443 0025424 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/source/platform/appinit.h 0000664 0000000 0000000 00000005264 14615113443 0027250 0 ustar 00root root 0000000 0000000 //------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : AudioHost
// Filename : public.sdk/samples/vst-hosting/audiohost/source/platform/appinit.h
// Created by : Steinberg, 04/2005
// Description : Audio Host Example for VST 3
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/iapplication.h"
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace AudioHost {
//------------------------------------------------------------------------
struct AppInit
{
explicit AppInit (EditorHost::ApplicationPtr&& _app) { app = std::move (_app); }
EditorHost::ApplicationPtr app;
};
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/audiohost/source/usediids.cpp 0000664 0000000 0000000 00000004755 14615113443 0026130 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : AudioHost
// Filename : public.sdk/samples/vst-hosting/audiohost/source/usediids.cpp
// Created by : Steinberg 09.2008
// Description : Audio Host Example for VST 3
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
//#define INIT_CLASS_IID
// This macro definition modifies the behavior of DECLARE_CLASS_IID (funknown.h)
// and produces the actual symbols for all interface identifiers.
// It must be defined before including the interface headers and
// in only one source file!
//------------------------------------------------------------------------
//#define INIT_CLASS_IID
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/ 0000775 0000000 0000000 00000000000 14615113443 0022465 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/CMakeLists.txt 0000664 0000000 0000000 00000006631 14615113443 0025233 0 ustar 00root root 0000000 0000000
if(SMTG_ENABLE_VST3_HOSTING_EXAMPLES)
set(editorhost_sources
${SDK_ROOT}/public.sdk/source/vst/hosting/plugprovider.cpp
${SDK_ROOT}/public.sdk/source/vst/hosting/plugprovider.h
source/editorhost.cpp
source/editorhost.h
source/platform/appinit.h
source/platform/iapplication.h
source/platform/iplatform.h
source/platform/iwindow.h
source/usediids.cpp
)
if(SMTG_MAC)
set(editorhost_sources
${editorhost_sources}
source/platform/mac/platform.mm
source/platform/mac/window.h
source/platform/mac/window.mm
${SDK_ROOT}/public.sdk/source/vst/hosting/module_mac.mm
)
set_source_files_properties(
source/platform/mac/window.mm
source/platform/mac/platform.mm
"${SDK_ROOT}/public.sdk/source/vst/hosting/module_mac.mm" PROPERTIES
COMPILE_FLAGS "-fobjc-arc"
)
set(editorhost_PLATFORM_LIBS
"-framework Cocoa"
)
get_filename_component(InfoPlistFile "resource/Info.plist" ABSOLUTE)
set(APP_PROPERTIES
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_INFO_PLIST ${InfoPlistFile}
)
elseif(SMTG_LINUX)
find_package(X11 REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
pkg_check_modules(GTKMM3 REQUIRED gtkmm-3.0)
include_directories(${X11_INCLUDE_DIR} ${GTKMM3_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS})
set(editorhost_sources
${editorhost_sources}
source/platform/linux/platform.cpp
source/platform/linux/runloop.h
source/platform/linux/runloop.cpp
source/platform/linux/window.h
source/platform/linux/window.cpp
${SDK_ROOT}/public.sdk/source/vst/hosting/module_linux.cpp
)
set(editorhost_PLATFORM_LIBS
${X11_LIBRARIES}
${GTK3_LIBRARIES}
${GTKMM3_LIBRARIES}
)
set(APP_PROPERTIES
)
elseif(SMTG_WIN)
set(editorhost_sources
${editorhost_sources}
source/platform/win32/platform.cpp
source/platform/win32/window.h
source/platform/win32/window.cpp
${SDK_ROOT}/public.sdk/source/vst/hosting/module_win32.cpp
)
set(editorhost_PLATFORM_LIBS
)
if(MSVC)
set(APP_PROPERTIES
LINK_FLAGS "/SUBSYSTEM:windows"
)
endif(MSVC)
if(MINGW)
# It causes the UNICODE preprocessor macro to be predefined, and chooses Unicode-capable runtime startup code.
set(APP_PROPERTIES
LINK_FLAGS -municode
)
endif(MINGW)
endif(SMTG_MAC)
set(target editorhost)
add_executable(${target} ${editorhost_sources})
set_target_properties(${target}
PROPERTIES
${SDK_IDE_HOSTING_EXAMPLES_FOLDER}
)
target_compile_features(${target}
PUBLIC
cxx_std_17
)
target_link_libraries(${target}
PRIVATE
sdk_hosting
${editorhost_PLATFORM_LIBS}
)
smtg_target_setup_universal_binary(${target})
if (APP_PROPERTIES)
set_target_properties(${target}
PROPERTIES
${APP_PROPERTIES}
)
endif(APP_PROPERTIES)
endif(SMTG_ENABLE_VST3_HOSTING_EXAMPLES)
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/resource/ 0000775 0000000 0000000 00000000000 14615113443 0024314 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/resource/Info.plist 0000664 0000000 0000000 00000004125 14615113443 0026266 0 ustar 00root root 0000000 0000000
CFBundleDevelopmentRegion
en
CFBundleExecutable
editorhost
CFBundleIdentifier
com.steinberg.vstsdk.editorhost
CFBundleInfoDictionaryVersion
6.0
CFBundleName
editorhost
CFBundlePackageType
BNDL
CFBundleShortVersionString
1.0.0
CFBundleVersion
1
NSHumanReadableCopyright
Copyright © 2020 Steinberg. All rights reserved.
NSPrincipalClass
NSApplication
CFBundleDocumentTypes
CFBundleTypeExtensions
vst3
CFBundleTypeName
VST3 Plug-In
CFBundleTypeRole
Editor
UTImportedTypeDeclarations
UTTypeConformsTo
public.data
public.content
UTTypeDescription
VST3 Plug-In
UTTypeIdentifier
com.steinberg.vst3.plugin
UTTypeTagSpecification
public.filename-extension
vst3
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/ 0000775 0000000 0000000 00000000000 14615113443 0023765 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/editorhost.cpp 0000664 0000000 0000000 00000032546 14615113443 0026667 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/editorhost.cpp
// Created by : Steinberg 09.2016
// Description : Example of opening a plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#include "public.sdk/samples/vst-hosting/editorhost/source/editorhost.h"
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/appinit.h"
#include "base/source/fcommandline.h"
#include "base/source/fdebug.h"
#include "pluginterfaces/base/funknown.h"
#include "pluginterfaces/gui/iplugview.h"
#include "pluginterfaces/gui/iplugviewcontentscalesupport.h"
#include "pluginterfaces/vst/ivstaudioprocessor.h"
#include "pluginterfaces/vst/ivsteditcontroller.h"
#include "pluginterfaces/vst/vsttypes.h"
#include
#include
//------------------------------------------------------------------------
namespace Steinberg {
//------------------------------------------------------------------------
inline bool operator== (const ViewRect& r1, const ViewRect& r2)
{
return memcmp (&r1, &r2, sizeof (ViewRect)) == 0;
}
//------------------------------------------------------------------------
inline bool operator!= (const ViewRect& r1, const ViewRect& r2)
{
return !(r1 == r2);
}
namespace Vst {
namespace EditorHost {
static AppInit gInit (std::make_unique ());
//------------------------------------------------------------------------
class WindowController : public IWindowController, public IPlugFrame
{
public:
WindowController (const IPtr& plugView);
~WindowController () noexcept override;
void onShow (IWindow& w) override;
void onClose (IWindow& w) override;
void onResize (IWindow& w, Size newSize) override;
Size constrainSize (IWindow& w, Size requestedSize) override;
void onContentScaleFactorChanged (IWindow& window, float newScaleFactor) override;
// IPlugFrame
tresult PLUGIN_API resizeView (IPlugView* view, ViewRect* newSize) override;
void closePlugView ();
private:
tresult PLUGIN_API queryInterface (const TUID _iid, void** obj) override
{
if (FUnknownPrivate::iidEqual (_iid, IPlugFrame::iid) ||
FUnknownPrivate::iidEqual (_iid, FUnknown::iid))
{
*obj = this;
addRef ();
return kResultTrue;
}
if (window)
return window->queryInterface (_iid, obj);
return kNoInterface;
}
// we do not care here of the ref-counting. A plug-in call of release should not destroy this
// class!
uint32 PLUGIN_API addRef () override { return 1000; }
uint32 PLUGIN_API release () override { return 1000; }
IPtr plugView;
IWindow* window {nullptr};
bool resizeViewRecursionGard {false};
};
//------------------------------------------------------------------------
class ComponentHandler : public IComponentHandler
{
public:
tresult PLUGIN_API beginEdit (ParamID id) override
{
SMTG_DBPRT1 ("beginEdit called (%d)\n", id);
return kNotImplemented;
}
tresult PLUGIN_API performEdit (ParamID id, ParamValue valueNormalized) override
{
SMTG_DBPRT2 ("performEdit called (%d, %f)\n", id, valueNormalized);
return kNotImplemented;
}
tresult PLUGIN_API endEdit (ParamID id) override
{
SMTG_DBPRT1 ("endEdit called (%d)\n", id);
return kNotImplemented;
}
tresult PLUGIN_API restartComponent (int32 flags) override
{
SMTG_DBPRT1 ("restartComponent called (%d)\n", flags);
return kNotImplemented;
}
private:
tresult PLUGIN_API queryInterface (const TUID /*_iid*/, void** /*obj*/) override
{
return kNoInterface;
}
// we do not care here of the ref-counting. A plug-in call of release should not destroy this
// class!
uint32 PLUGIN_API addRef () override { return 1000; }
uint32 PLUGIN_API release () override { return 1000; }
};
static ComponentHandler gComponentHandler;
//------------------------------------------------------------------------
App::~App () noexcept
{
terminate ();
}
//------------------------------------------------------------------------
void App::openEditor (const std::string& path, VST3::Optional effectID, uint32 flags)
{
std::string error;
module = VST3::Hosting::Module::create (path, error);
if (!module)
{
std::string reason = "Could not create Module for file:";
reason += path;
reason += "\nError: ";
reason += error;
IPlatform::instance ().kill (-1, reason);
}
auto factory = module->getFactory ();
if (auto factoryHostContext = IPlatform::instance ().getPluginFactoryContext ())
factory.setHostContext (factoryHostContext);
for (auto& classInfo : factory.classInfos ())
{
if (classInfo.category () == kVstAudioEffectClass)
{
if (effectID)
{
if (*effectID != classInfo.ID ())
continue;
}
plugProvider = owned (new PlugProvider (factory, classInfo, true));
if (plugProvider->initialize () == false)
plugProvider = nullptr;
break;
}
}
if (!plugProvider)
{
if (effectID)
error =
"No VST3 Audio Module Class with UID " + effectID->toString () + " found in file ";
else
error = "No VST3 Audio Module Class found in file ";
error += path;
IPlatform::instance ().kill (-1, error);
}
auto editController = plugProvider->getController ();
if (!editController)
{
error = "No EditController found (needed for allowing editor) in file " + path;
IPlatform::instance ().kill (-1, error);
}
editController->release (); // plugProvider does an addRef
if (flags & kSetComponentHandler)
{
SMTG_DBPRT0 ("setComponentHandler is used\n");
editController->setComponentHandler (&gComponentHandler);
}
SMTG_DBPRT1 ("Open Editor for %s...\n", path.c_str ());
createViewAndShow (editController);
if (flags & kSecondWindow)
{
SMTG_DBPRT0 ("Open 2cd Editor...\n");
createViewAndShow (editController);
}
}
//------------------------------------------------------------------------
void App::createViewAndShow (IEditController* controller)
{
auto view = owned (controller->createView (ViewType::kEditor));
if (!view)
{
IPlatform::instance ().kill (-1, "EditController does not provide its own editor");
}
ViewRect plugViewSize {};
auto result = view->getSize (&plugViewSize);
if (result != kResultTrue)
{
IPlatform::instance ().kill (-1, "Could not get editor view size");
}
auto viewRect = ViewRectToRect (plugViewSize);
windowController = std::make_shared (view);
window = IPlatform::instance ().createWindow (
"Editor", viewRect.size, view->canResize () == kResultTrue, windowController);
if (!window)
{
IPlatform::instance ().kill (-1, "Could not create window");
}
window->show ();
}
//------------------------------------------------------------------------
void App::init (const std::vector& cmdArgs)
{
VST3::Optional uid;
uint32 flags {};
for (auto it = cmdArgs.begin (), end = cmdArgs.end (); it != end; ++it)
{
if (*it == "--componentHandler")
flags |= kSetComponentHandler;
else if (*it == "--secondWindow")
flags |= kSecondWindow;
else if (*it == "--uid")
{
if (++it != end)
uid = VST3::UID::fromString (*it);
if (!uid)
IPlatform::instance ().kill (-1, "wrong argument to --uid");
}
}
if (cmdArgs.empty () || cmdArgs.back ().find (".vst3") == std::string::npos)
{
auto helpText = R"(
usage: EditorHost [options] pluginPath
options:
--componentHandler
set optional component handler on edit controller
--secondWindow
create a second window
--uid UID
use effect class with unique class ID==UID
)";
IPlatform::instance ().kill (0, helpText);
}
PluginContextFactory::instance ().setPluginContext (&pluginContext);
openEditor (cmdArgs.back (), std::move (uid), flags);
}
//------------------------------------------------------------------------
void App::terminate ()
{
if (windowController)
windowController->closePlugView ();
windowController.reset ();
plugProvider.reset ();
module.reset ();
PluginContextFactory::instance ().setPluginContext (nullptr);
}
//------------------------------------------------------------------------
WindowController::WindowController (const IPtr& plugView) : plugView (plugView)
{
}
//------------------------------------------------------------------------
WindowController::~WindowController () noexcept
{
}
//------------------------------------------------------------------------
void WindowController::onShow (IWindow& w)
{
SMTG_DBPRT1 ("onShow called (%p)\n", (void*)&w);
window = &w;
if (!plugView)
return;
auto platformWindow = window->getNativePlatformWindow ();
if (plugView->isPlatformTypeSupported (platformWindow.type) != kResultTrue)
{
IPlatform::instance ().kill (-1, std::string ("PlugView does not support platform type:") +
platformWindow.type);
}
plugView->setFrame (this);
if (plugView->attached (platformWindow.ptr, platformWindow.type) != kResultTrue)
{
IPlatform::instance ().kill (-1, "Attaching PlugView failed");
}
}
//------------------------------------------------------------------------
void WindowController::closePlugView ()
{
if (plugView)
{
plugView->setFrame (nullptr);
if (plugView->removed () != kResultTrue)
{
IPlatform::instance ().kill (-1, "Removing PlugView failed");
}
plugView = nullptr;
}
window = nullptr;
}
//------------------------------------------------------------------------
void WindowController::onClose (IWindow& w)
{
SMTG_DBPRT1 ("onClose called (%p)\n", (void*)&w);
closePlugView ();
// TODO maybe quit only when the last window is closed
IPlatform::instance ().quit ();
}
//------------------------------------------------------------------------
void WindowController::onResize (IWindow& w, Size newSize)
{
SMTG_DBPRT1 ("onResize called (%p)\n", (void*)&w);
if (plugView)
{
ViewRect r {};
r.right = newSize.width;
r.bottom = newSize.height;
ViewRect r2 {};
if (plugView->getSize (&r2) == kResultTrue && r != r2)
plugView->onSize (&r);
}
}
//------------------------------------------------------------------------
Size WindowController::constrainSize (IWindow& w, Size requestedSize)
{
SMTG_DBPRT1 ("constrainSize called (%p)\n", (void*)&w);
ViewRect r {};
r.right = requestedSize.width;
r.bottom = requestedSize.height;
if (plugView && plugView->checkSizeConstraint (&r) != kResultTrue)
{
plugView->getSize (&r);
}
requestedSize.width = r.right - r.left;
requestedSize.height = r.bottom - r.top;
return requestedSize;
}
//------------------------------------------------------------------------
void WindowController::onContentScaleFactorChanged (IWindow& w, float newScaleFactor)
{
SMTG_DBPRT1 ("onContentScaleFactorChanged called (%p)\n", (void*)&w);
FUnknownPtr css (plugView);
if (css)
{
css->setContentScaleFactor (newScaleFactor);
}
}
//------------------------------------------------------------------------
tresult PLUGIN_API WindowController::resizeView (IPlugView* view, ViewRect* newSize)
{
SMTG_DBPRT1 ("resizeView called (%p)\n", (void*)view);
if (newSize == nullptr || view == nullptr || view != plugView)
return kInvalidArgument;
if (!window)
return kInternalError;
if (resizeViewRecursionGard)
return kResultFalse;
ViewRect r;
if (plugView->getSize (&r) != kResultTrue)
return kInternalError;
if (r == *newSize)
return kResultTrue;
resizeViewRecursionGard = true;
Size size {newSize->right - newSize->left, newSize->bottom - newSize->top};
window->resize (size);
resizeViewRecursionGard = false;
if (plugView->getSize (&r) != kResultTrue)
return kInternalError;
if (r != *newSize)
plugView->onSize (newSize);
return kResultTrue;
}
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/editorhost.h 0000664 0000000 0000000 00000006717 14615113443 0026335 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/editorhost.h
// Created by : Steinberg 09.2016
// Description : Example of opening a Plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/iapplication.h"
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/iwindow.h"
#include "public.sdk/source/vst/hosting/hostclasses.h"
#include "public.sdk/source/vst/hosting/module.h"
#include "public.sdk/source/vst/hosting/plugprovider.h"
#include "public.sdk/source/vst/utility/optional.h"
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace EditorHost {
class WindowController;
//------------------------------------------------------------------------
class App : public IApplication
{
public:
~App () noexcept override;
void init (const std::vector& cmdArgs) override;
void terminate () override;
private:
enum OpenFlags
{
kSetComponentHandler = 1 << 0,
kSecondWindow = 1 << 1,
};
void openEditor (const std::string& path, VST3::Optional effectID, uint32 flags);
void createViewAndShow (IEditController* controller);
VST3::Hosting::Module::Ptr module {nullptr};
IPtr plugProvider {nullptr};
Vst::HostApplication pluginContext;
WindowPtr window;
std::shared_ptr windowController;
};
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/ 0000775 0000000 0000000 00000000000 14615113443 0025611 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/appinit.h 0000664 0000000 0000000 00000005403 14615113443 0027430 0 ustar 00root root 0000000 0000000 //------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/platform/appinit.h
// Created by : Steinberg, 04/2005
// Description : Editor Host Example for VST SDK 3
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/iapplication.h"
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/iplatform.h"
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace EditorHost {
//------------------------------------------------------------------------
struct AppInit
{
explicit AppInit (ApplicationPtr&& app)
{
IPlatform::instance ().setApplication (std::move (app));
}
};
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/iapplication.h 0000664 0000000 0000000 00000005411 14615113443 0030437 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/platform/iapplication.h
// Created by : Steinberg 09.2016
// Description : Example of opening a plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include
#include
#include
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace EditorHost {
//------------------------------------------------------------------------
class IApplication
{
public:
virtual ~IApplication () noexcept = default;
virtual void init (const std::vector& cmdArgs) = 0;
virtual void terminate () = 0;
};
using ApplicationPtr = std::unique_ptr;
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/iplatform.h 0000664 0000000 0000000 00000006271 14615113443 0027765 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/platform/iplatform.h
// Created by : Steinberg 09.2016
// Description : Example of opening a plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/iapplication.h"
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/iwindow.h"
#include
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace EditorHost {
//------------------------------------------------------------------------
class IPlatform
{
public:
virtual ~IPlatform () noexcept = default;
virtual void setApplication (ApplicationPtr&& app) = 0;
virtual WindowPtr createWindow (const std::string& title, Size size, bool resizeable,
const WindowControllerPtr& controller) = 0;
virtual void quit () = 0;
virtual void kill (int resultCode, const std::string& reason) = 0;
virtual FUnknown* getPluginFactoryContext () = 0;
static IPlatform& instance ();
};
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
extern void ApplicationInit (int argc, const char* argv[]);
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/iwindow.h 0000664 0000000 0000000 00000011213 14615113443 0027440 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/platform/iwindow.h
// Created by : Steinberg 09.2016
// Description : Example of opening a plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include "pluginterfaces/gui/iplugview.h"
#include
#include
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace EditorHost {
using Coord = int32_t;
//------------------------------------------------------------------------
struct Point
{
Coord x;
Coord y;
};
//------------------------------------------------------------------------
struct Size
{
Coord width;
Coord height;
};
//------------------------------------------------------------------------
inline bool operator!= (const Size& lhs, const Size& rhs)
{
return lhs.width != rhs.width || lhs.height != rhs.height;
}
//------------------------------------------------------------------------
inline bool operator== (const Size& lhs, const Size& rhs)
{
return lhs.width == rhs.width && lhs.height == rhs.height;
}
//------------------------------------------------------------------------
struct Rect
{
Point origin;
Size size;
};
//------------------------------------------------------------------------
inline Rect ViewRectToRect (ViewRect r)
{
Rect result {};
result.origin.x = r.left;
result.origin.y = r.top;
result.size.width = r.right - r.left;
result.size.height = r.bottom - r.top;
return result;
}
//------------------------------------------------------------------------
struct NativePlatformWindow
{
FIDString type;
void* ptr;
};
class IWindow;
//------------------------------------------------------------------------
class IWindowController
{
public:
virtual ~IWindowController () noexcept = default;
virtual void onShow (IWindow& window) = 0;
virtual void onClose (IWindow& window) = 0;
virtual void onResize (IWindow& window, Size newSize) = 0;
virtual void onContentScaleFactorChanged (IWindow& window, float newScaleFactor) = 0;
virtual Size constrainSize (IWindow& window, Size requestedSize) = 0;
};
using WindowControllerPtr = std::shared_ptr;
//------------------------------------------------------------------------
class IWindow
{
public:
virtual ~IWindow () noexcept = default;
virtual void show () = 0;
virtual void close () = 0;
virtual void resize (Size newSize) = 0;
virtual Size getContentSize () = 0;
virtual NativePlatformWindow getNativePlatformWindow () const = 0;
virtual tresult queryInterface (const TUID iid, void** obj) = 0;
};
using WindowPtr = std::shared_ptr;
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/linux/ 0000775 0000000 0000000 00000000000 14615113443 0026750 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/linux/irunloopimpl.h 0000664 0000000 0000000 00000013016 14615113443 0031653 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/platform/linux/irunloopimpl.h
// Created by : Steinberg 09.2023
// Description : Example of opening a plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2023, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/linux/runloop.h"
#include "pluginterfaces/base/funknownimpl.h"
#include "pluginterfaces/gui/iplugview.h"
#include
//------------------------------------------------------------------------
namespace Steinberg {
namespace Linux {
//------------------------------------------------------------------------
class RunLoopImpl : U::ImplementsNonDestroyable>
{
public:
static IRunLoop& instance ()
{
static RunLoopImpl impl;
return impl;
}
tresult PLUGIN_API registerEventHandler (IEventHandler* handler, FileDescriptor fd) override;
tresult PLUGIN_API unregisterEventHandler (IEventHandler* handler) override;
tresult PLUGIN_API registerTimer (ITimerHandler* handler, TimerInterval milliseconds) override;
tresult PLUGIN_API unregisterTimer (ITimerHandler* handler) override;
private:
using TimerID = uint64_t;
using EventHandler = IPtr;
using TimerHandler = IPtr;
using EventHandlers = std::unordered_map;
using TimerHandlers = std::unordered_map;
EventHandlers eventHandlers;
TimerHandlers timerHandlers;
};
//------------------------------------------------------------------------
inline tresult PLUGIN_API RunLoopImpl::registerEventHandler (IEventHandler* handler,
FileDescriptor fd)
{
if (!handler || eventHandlers.find (fd) != eventHandlers.end ())
return kInvalidArgument;
Vst::EditorHost::RunLoop::instance ().registerFileDescriptor (
fd, [handler] (int fd) { handler->onFDIsSet (fd); });
eventHandlers.emplace (fd, handler);
return kResultTrue;
}
//------------------------------------------------------------------------
inline tresult PLUGIN_API RunLoopImpl::unregisterEventHandler (IEventHandler* handler)
{
if (!handler)
return kInvalidArgument;
auto it = std::find_if (eventHandlers.begin (), eventHandlers.end (),
[&] (const auto& elem) { return elem.second == handler; });
if (it == eventHandlers.end ())
return kResultFalse;
Vst::EditorHost::RunLoop::instance ().unregisterFileDescriptor (it->first);
eventHandlers.erase (it);
return kResultTrue;
}
//------------------------------------------------------------------------
inline tresult PLUGIN_API RunLoopImpl::registerTimer (ITimerHandler* handler,
TimerInterval milliseconds)
{
if (!handler || milliseconds == 0)
return kInvalidArgument;
auto id = Vst::EditorHost::RunLoop::instance ().registerTimer (
milliseconds, [handler] (auto) { handler->onTimer (); });
timerHandlers.emplace (id, handler);
return kResultTrue;
}
//------------------------------------------------------------------------
inline tresult PLUGIN_API RunLoopImpl::unregisterTimer (ITimerHandler* handler)
{
if (!handler)
return kInvalidArgument;
auto it = std::find_if (timerHandlers.begin (), timerHandlers.end (),
[&] (const auto& elem) { return elem.second == handler; });
if (it == timerHandlers.end ())
return kResultFalse;
Vst::EditorHost::RunLoop::instance ().unregisterTimer (it->first);
timerHandlers.erase (it);
return kResultTrue;
}
//------------------------------------------------------------------------
} // Linux
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/linux/platform.cpp 0000664 0000000 0000000 00000015667 14615113443 0031317 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/platform/linux/platform.cpp
// Created by : Steinberg 09.2016
// Description : Example of opening a plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/iplatform.h"
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/linux/window.h"
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/linux/irunloopimpl.h"
#include
#include
#include
#include
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace EditorHost {
using namespace std::chrono;
using clock = high_resolution_clock;
//------------------------------------------------------------------------
static int pause (int milliSeconds)
{
struct timeval timeOut;
if (milliSeconds > 0)
{
timeOut.tv_usec = (milliSeconds % (unsigned long)1000) * 1000;
timeOut.tv_sec = milliSeconds / (unsigned long)1000;
select (0, nullptr, nullptr, nullptr, &timeOut);
}
return (milliSeconds > 0 ? milliSeconds : 0);
}
//------------------------------------------------------------------------
//------------------------------------------------------------------------
class Platform : public IPlatform
{
public:
static Platform& instance ()
{
static Platform gInstance;
return gInstance;
}
void setApplication (ApplicationPtr&& app) override;
WindowPtr createWindow (const std::string& title, Size size, bool resizeable,
const WindowControllerPtr& controller) override;
void quit () override;
void kill (int resultCode, const std::string& reason) override;
FUnknown* getPluginFactoryContext () override;
void run (const std::vector& cmdArgs);
static const int kMinEventLoopRate = 16; // 60Hz
private:
void onWindowClosed (X11Window* window);
void closeAllWindows ();
void eventLoop ();
ApplicationPtr application;
Display* xDisplay {nullptr};
std::vector> windows;
};
//------------------------------------------------------------------------
IPlatform& IPlatform::instance ()
{
return Platform::instance ();
}
//------------------------------------------------------------------------
void Platform::setApplication (ApplicationPtr&& app)
{
application = std::move (app);
}
//------------------------------------------------------------------------
WindowPtr Platform::createWindow (const std::string& title, Size size, bool resizeable,
const WindowControllerPtr& controller)
{
auto window = X11Window::make (title, size, resizeable, controller, xDisplay,
[this] (X11Window* window) { onWindowClosed (window); });
if (window)
windows.push_back (std::static_pointer_cast (window));
return window;
}
//------------------------------------------------------------------------
void Platform::onWindowClosed (X11Window* window)
{
for (auto it = windows.begin (); it != windows.end (); ++it)
{
if (it->get () == window)
{
windows.erase (it);
break;
}
}
}
//------------------------------------------------------------------------
void Platform::closeAllWindows ()
{
for (auto& w : windows)
{
w->close ();
}
}
//------------------------------------------------------------------------
void Platform::quit ()
{
static bool recursiveGuard = false;
if (recursiveGuard)
return;
recursiveGuard = true;
closeAllWindows ();
if (application)
application->terminate ();
RunLoop::instance ().stop ();
recursiveGuard = false;
}
//------------------------------------------------------------------------
void Platform::kill (int resultCode, const std::string& reason)
{
std::cout << reason << "\n";
exit (resultCode);
}
//------------------------------------------------------------------------
FUnknown* Platform::getPluginFactoryContext ()
{
return &Steinberg::Linux::RunLoopImpl::instance ();
}
//------------------------------------------------------------------------
void Platform::run (const std::vector& cmdArgs)
{
// Connect to X server
std::string displayName (getenv ("DISPLAY"));
if (displayName.empty ())
displayName = ":0.0";
if ((xDisplay = XOpenDisplay (displayName.data ())) == nullptr)
{
return;
}
RunLoop::instance ().setDisplay (xDisplay);
application->init (cmdArgs);
eventLoop ();
XCloseDisplay (xDisplay);
}
//------------------------------------------------------------------------
void Platform::eventLoop ()
{
RunLoop::instance ().start ();
}
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
//------------------------------------------------------------------------
//------------------------------------------------------------------------
int main (int argc, char* argv[])
{
std::vector cmdArgs;
for (int i = 1; i < argc; ++i)
cmdArgs.push_back (argv[i]);
Steinberg::Vst::EditorHost::Platform::instance ().run (cmdArgs);
return 0;
}
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/linux/runloop.cpp 0000664 0000000 0000000 00000021053 14615113443 0031153 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/platform/linux/runloop.cpp
// Created by : Steinberg 09.2016
// Description : Example of opening a plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/linux/runloop.h"
#include
#include
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace EditorHost {
using LockGuard = std::lock_guard;
//------------------------------------------------------------------------
RunLoop& RunLoop::instance ()
{
static RunLoop gInstance;
return gInstance;
}
//------------------------------------------------------------------------
void RunLoop::setDisplay (Display* display)
{
this->display = display;
}
//------------------------------------------------------------------------
void RunLoop::registerWindow (XID window, const EventCallback& callback)
{
map.emplace (window, callback);
}
//------------------------------------------------------------------------
void RunLoop::unregisterWindow (XID window)
{
auto it = map.find (window);
if (it == map.end ())
return;
map.erase (it);
}
//------------------------------------------------------------------------
void RunLoop::registerFileDescriptor (int fd, const FileDescriptorCallback& callback)
{
fileDescriptors.emplace (fd, callback);
}
//------------------------------------------------------------------------
void RunLoop::unregisterFileDescriptor (int fd)
{
auto it = fileDescriptors.find (fd);
if (it == fileDescriptors.end ())
return;
fileDescriptors.erase (it);
}
//------------------------------------------------------------------------
void RunLoop::select (timeval* timeout)
{
int nfds = 0;
fd_set readFDs = {}, writeFDs = {}, exceptFDs = {};
for (auto& e : fileDescriptors)
{
int fd = e.first;
FD_SET (fd, &readFDs);
FD_SET (fd, &writeFDs);
FD_SET (fd, &exceptFDs);
nfds = std::max (nfds, fd);
}
int result = ::select (nfds, &readFDs, &writeFDs, nullptr, timeout);
if (result > 0)
{
for (auto& e : fileDescriptors)
{
if (FD_ISSET (e.first, &readFDs) || FD_ISSET (e.first, &writeFDs) ||
FD_ISSET (e.first, &exceptFDs))
e.second (e.first);
}
}
}
//------------------------------------------------------------------------
bool RunLoop::handleEvents ()
{
auto count = XPending (display);
if (count == 0)
return false;
for (auto i = 0; i < count; ++i)
{
XEvent event {};
XNextEvent (display, &event);
auto it = map.find (event.xany.window);
if (it != map.end ())
{
it->second (event);
if (event.type == DestroyNotify)
{
map.erase (it);
}
}
else
{
XPutBackEvent (display, &event);
break;
}
}
return true;
}
//------------------------------------------------------------------------
TimerID RunLoop::registerTimer (TimerInterval interval, const TimerCallback& callback)
{
return timerProcessor.registerTimer (interval, callback);
}
//------------------------------------------------------------------------
void RunLoop::unregisterTimer (TimerID id)
{
timerProcessor.unregisterTimer (id);
}
//------------------------------------------------------------------------
bool timeValEmpty (timeval& val)
{
return val.tv_sec == 0 && val.tv_usec == 0;
}
//------------------------------------------------------------------------
void RunLoop::start ()
{
using namespace std::chrono;
using clock = high_resolution_clock;
running = true;
auto fd = XConnectionNumber (display);
registerFileDescriptor (fd, [this] (int) { handleEvents (); });
XSync (display, false);
handleEvents ();
timeval selectTimeout {};
while (running && !map.empty ())
{
select (timeValEmpty (selectTimeout) ? nullptr : &selectTimeout);
auto nextFireTime = timerProcessor.handleTimersAndReturnNextFireTimeInMs ();
if (nextFireTime == TimerProcessor::noTimers)
{
selectTimeout = {};
}
else
{
selectTimeout.tv_sec = nextFireTime / 1000;
selectTimeout.tv_usec = (nextFireTime - (selectTimeout.tv_sec * 1000)) * 1000;
}
}
}
//------------------------------------------------------------------------
void RunLoop::stop ()
{
running = false;
}
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//------------------------------------------------------------------------
uint64_t TimerProcessor::handleTimersAndReturnNextFireTimeInMs ()
{
using std::chrono::time_point_cast;
if (timers.empty ())
return noTimers;
auto current = time_point_cast (Clock::now ());
std::vector timersToFire;
for (auto& timer : timers)
{
if (timer.nextFireTime > current)
break;
timersToFire.push_back (timer.id);
updateTimerNextFireTime (timer, current);
}
for (auto id : timersToFire)
{
for (auto& timer : timers)
{
if (timer.id == id)
{
timer.callback (timer.id);
break;
}
}
}
if (timersToFire.empty ())
return noTimers;
sortTimers ();
auto nextFireTime = timers.front ().nextFireTime;
current = now ();
if (nextFireTime < current)
return 0;
return (nextFireTime - current).count ();
}
//------------------------------------------------------------------------
void TimerProcessor::updateTimerNextFireTime (Timer& timer, TimePoint current)
{
timer.nextFireTime = current + Millisecond (timer.interval);
}
//------------------------------------------------------------------------
void TimerProcessor::sortTimers ()
{
std::sort (timers.begin (), timers.end (),
[] (const Timer& t1, const Timer& t2) { return t1.nextFireTime < t2.nextFireTime; });
}
//------------------------------------------------------------------------
auto TimerProcessor::now () -> TimePoint
{
using std::chrono::time_point_cast;
return time_point_cast (Clock::now ());
}
//------------------------------------------------------------------------
auto TimerProcessor::registerTimer (TimerInterval interval, const TimerCallback& callback)
-> TimerID
{
auto timerId = ++timerIdCounter;
Timer timer;
timer.id = timerId;
timer.callback = callback;
timer.interval = interval;
updateTimerNextFireTime (timer, now ());
timers.emplace_back (std::move (timer));
sortTimers ();
return timerId;
}
//------------------------------------------------------------------------
void TimerProcessor::unregisterTimer (TimerID id)
{
for (auto it = timers.begin (), end = timers.end (); it != end; ++it)
{
if (it->id == id)
{
timers.erase (it);
break;
}
}
}
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/linux/runloop.h 0000664 0000000 0000000 00000011051 14615113443 0030615 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/platform/linux/runloop.h
// Created by : Steinberg 09.2016
// Description : Example of opening a plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include
#include
#include
#include
#include
#include
#include
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace EditorHost {
//------------------------------------------------------------------------
using TimerID = uint64_t;
using TimerInterval = uint64_t;
using TimerCallback = std::function;
//------------------------------------------------------------------------
class TimerProcessor
{
public:
TimerID registerTimer (TimerInterval interval, const TimerCallback& callback);
void unregisterTimer (TimerID id);
static constexpr uint64_t noTimers = std::numeric_limits::max ();
uint64_t handleTimersAndReturnNextFireTimeInMs ();
private:
using Clock = std::chrono::steady_clock;
using Millisecond = std::chrono::milliseconds;
using TimePoint = std::chrono::time_point;
struct Timer
{
TimerID id;
TimerInterval interval;
TimerCallback callback;
TimePoint nextFireTime;
};
using Timers = std::vector;
Timers timers;
TimerID timerIdCounter {0};
void updateTimerNextFireTime (Timer& timer, TimePoint current);
void sortTimers ();
TimePoint now ();
};
//------------------------------------------------------------------------
class RunLoop
{
public:
using EventCallback = std::function;
using FileDescriptorCallback = std::function;
static RunLoop& instance ();
void setDisplay (Display* display);
void registerWindow (XID window, const EventCallback& callback);
void unregisterWindow (XID window);
void registerFileDescriptor (int fd, const FileDescriptorCallback& callback);
void unregisterFileDescriptor (int fd);
TimerID registerTimer (TimerInterval interval, const TimerCallback& callback);
void unregisterTimer (TimerID id);
void start ();
void stop ();
private:
void select (timeval* timeout = nullptr);
bool handleEvents ();
using WindowMap = std::unordered_map;
using FileDescriptorCallbacks = std::unordered_map;
WindowMap map;
FileDescriptorCallbacks fileDescriptors;
TimerProcessor timerProcessor;
Display* display {nullptr};
bool running {false};
};
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/linux/window.cpp 0000664 0000000 0000000 00000045600 14615113443 0030770 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/platform/linux/window.cpp
// Created by : Steinberg 09.2016
// Description : Example of opening a plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#include "window.h"
#include "public.sdk/source/vst/utility/stringconvert.h"
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/linux/irunloopimpl.h"
#include
#include
#include
#include
#include
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace EditorHost {
//------------------------------------------------------------------------
struct X11Window::Impl
{
Impl (X11Window* x11Window);
bool init (const std::string& name, Size size, bool resizeable,
const WindowControllerPtr& controller, Display* display,
const WindowClosedFunc& windowClosedFunc);
void show ();
void close ();
Size getSize () const;
void resize (Size newSize, bool force);
//------------------------------------------------------------------------
struct XEmbedInfo
{
uint32_t version;
uint32_t flags;
};
~Impl ();
void onClose ();
bool handleMainWindowEvent (const XEvent& event);
bool handlePlugEvent (const XEvent& event);
XEmbedInfo* getXEmbedInfo ();
void checkSize ();
void callPlugEventHandlers ();
WindowControllerPtr controller {nullptr};
WindowClosedFunc windowClosedFunc;
Display* xDisplay {nullptr};
XEmbedInfo* xembedInfo {nullptr};
Window xWindow {};
Window plugParentWindow {};
Window plugWindow {};
GC xGraphicContext {};
Atom xEmbedInfoAtom {None};
Atom xEmbedAtom {None};
bool isMapped {false};
using EventHandler = IPtr;
using TimerHandler = IPtr;
Size mCurrentSize {};
X11Window* x11Window {nullptr};
};
//------------------------------------------------------------------------
auto X11Window::make (const std::string& name, Size size, bool resizeable,
const WindowControllerPtr& controller, Display* display,
const WindowClosedFunc& windowClosedFunc) -> Ptr
{
auto window = std::make_shared ();
if (window->init (name, size, resizeable, controller, display, windowClosedFunc))
{
return window;
}
return nullptr;
}
//------------------------------------------------------------------------
X11Window::X11Window ()
{
impl = std::unique_ptr (new Impl (this));
}
//------------------------------------------------------------------------
X11Window::~X11Window ()
{
}
//------------------------------------------------------------------------
bool X11Window::init (const std::string& name, Size size, bool resizeable,
const WindowControllerPtr& controller, Display* display,
const WindowClosedFunc& windowClosedFunc)
{
return impl->init (name, size, resizeable, controller, display, windowClosedFunc);
}
//------------------------------------------------------------------------
Size X11Window::getSize () const
{
return impl->getSize ();
}
//------------------------------------------------------------------------
void X11Window::show ()
{
impl->show ();
}
//------------------------------------------------------------------------
void X11Window::close ()
{
impl->close ();
}
//------------------------------------------------------------------------
void X11Window::resize (Size newSize)
{
impl->resize (newSize, false);
}
//------------------------------------------------------------------------
Size X11Window::getContentSize ()
{
return {};
}
//------------------------------------------------------------------------
NativePlatformWindow X11Window::getNativePlatformWindow () const
{
return {kPlatformTypeX11EmbedWindowID, reinterpret_cast (impl->plugParentWindow)};
}
//------------------------------------------------------------------------
tresult X11Window::queryInterface (const TUID iid, void** obj)
{
if (FUnknownPrivate::iidEqual (iid, Linux::IRunLoop::iid))
{
*obj = &(Linux::RunLoopImpl::instance ());
// as the run loop is a singleton it is not necessary to call a retain on that object
return kResultTrue;
}
return kNoInterface;
}
//------------------------------------------------------------------------
void X11Window::onIdle ()
{
}
/* XEMBED messages */
#define XEMBED_EMBEDDED_NOTIFY 0
#define XEMBED_WINDOW_ACTIVATE 1
#define XEMBED_WINDOW_DEACTIVATE 2
#define XEMBED_REQUEST_FOCUS 3
#define XEMBED_FOCUS_IN 4
#define XEMBED_FOCUS_OUT 5
#define XEMBED_FOCUS_NEXT 6
#define XEMBED_FOCUS_PREV 7
/* 8-9 were used for XEMBED_GRAB_KEY/XEMBED_UNGRAB_KEY */
#define XEMBED_MODALITY_ON 10
#define XEMBED_MODALITY_OFF 11
#define XEMBED_REGISTER_ACCELERATOR 12
#define XEMBED_UNREGISTER_ACCELERATOR 13
#define XEMBED_ACTIVATE_ACCELERATOR 14
void send_xembed_message (Display* dpy, /* display */
Window w, /* receiver */
Atom messageType, long message, /* message opcode */
long detail, /* message detail */
long data1, /* message data 1 */
long data2 /* message data 2 */
)
{
XEvent ev;
memset (&ev, 0, sizeof (ev));
ev.xclient.type = ClientMessage;
ev.xclient.window = w;
ev.xclient.message_type = messageType;
ev.xclient.format = 32;
ev.xclient.data.l[0] = CurrentTime;
ev.xclient.data.l[1] = message;
ev.xclient.data.l[2] = detail;
ev.xclient.data.l[3] = data1;
ev.xclient.data.l[4] = data2;
XSendEvent (dpy, w, False, NoEventMask, &ev);
XSync (dpy, False);
}
#define XEMBED_MAPPED (1 << 0)
//------------------------------------------------------------------------
X11Window::Impl::Impl (X11Window* x11Window) : x11Window (x11Window)
{
}
//------------------------------------------------------------------------
X11Window::Impl::~Impl ()
{
}
//------------------------------------------------------------------------
bool X11Window::Impl::init (const std::string& name, Size size, bool resizeable,
const WindowControllerPtr& controller, Display* display,
const WindowClosedFunc& windowClosedFunc)
{
this->windowClosedFunc = windowClosedFunc;
this->controller = controller;
xDisplay = display;
xEmbedInfoAtom = XInternAtom (xDisplay, "_XEMBED_INFO", true);
if (xEmbedInfoAtom == None)
{
std::cerr << "_XEMBED_INFO does not exist" << std::endl;
return false;
}
// Get screen size from display
auto screen_num = DefaultScreen (xDisplay);
auto displayWidth = DisplayWidth (xDisplay, screen_num);
auto displayHeight = DisplayHeight (xDisplay, screen_num);
unsigned int border_width = 1;
XVisualInfo vInfo;
if (!XMatchVisualInfo (xDisplay, screen_num, 24, TrueColor, &vInfo))
{
exit (-1);
}
XSetWindowAttributes winAttr {};
winAttr.border_pixel = BlackPixel (xDisplay, screen_num);
winAttr.background_pixel = WhitePixel (xDisplay, screen_num);
winAttr.colormap =
XCreateColormap (xDisplay, XDefaultRootWindow (xDisplay), vInfo.visual, AllocNone);
uint32_t winAttrMask = CWBackPixel | CWColormap | CWBorderPixel;
xWindow = XCreateWindow (xDisplay, RootWindow (xDisplay, screen_num), 0, 0, displayWidth,
displayHeight, border_width, vInfo.depth, InputOutput, vInfo.visual,
winAttrMask, &winAttr);
XFlush (xDisplay);
resize (size, true);
XSelectInput (xDisplay, xWindow, /* KeyPressMask | ButtonPressMask |*/
ExposureMask | /*ResizeRedirectMask |*/ StructureNotifyMask |
SubstructureNotifyMask | FocusChangeMask);
auto sizeHints = XAllocSizeHints ();
sizeHints->flags = PMinSize;
if (!resizeable)
{
sizeHints->flags |= PMaxSize;
sizeHints->min_width = sizeHints->max_width = size.width;
sizeHints->min_height = sizeHints->max_height = size.height;
}
else
{
sizeHints->min_width = sizeHints->min_height = 80;
}
XSetWMNormalHints (xDisplay, xWindow, sizeHints);
XFree (sizeHints);
// set a title
XStoreName (xDisplay, xWindow, name.data ());
XTextProperty iconName;
auto icon_name = const_cast (name.data ());
XStringListToTextProperty (&icon_name, 1, &iconName);
XSetWMIconName (xDisplay, xWindow, &iconName);
Atom wm_delete_window;
wm_delete_window = XInternAtom (xDisplay, "WM_DELETE_WINDOW", False);
XSetWMProtocols (xDisplay, xWindow, &wm_delete_window, 1);
xGraphicContext = XCreateGC (xDisplay, xWindow, 0, 0);
XSetForeground (xDisplay, xGraphicContext, WhitePixel (xDisplay, screen_num));
XSetBackground (xDisplay, xGraphicContext, BlackPixel (xDisplay, screen_num));
winAttr = {};
winAttr.override_redirect = true;
winAttr.event_mask =
ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask;
plugParentWindow =
XCreateWindow (xDisplay, xWindow, 0, 0, size.width, size.height, border_width, vInfo.depth,
InputOutput, CopyFromParent, winAttrMask, &winAttr);
XSelectInput (xDisplay, plugParentWindow, SubstructureNotifyMask | PropertyChangeMask);
XMapWindow (xDisplay, plugParentWindow);
RunLoop::instance ().registerWindow (plugParentWindow,
[this] (const XEvent& e) { return handlePlugEvent (e); });
RunLoop::instance ().registerWindow (
xWindow, [this] (const XEvent& e) { return handleMainWindowEvent (e); });
return true;
}
//------------------------------------------------------------------------
void X11Window::Impl::show ()
{
XMapWindow (xDisplay, xWindow);
}
//------------------------------------------------------------------------
void X11Window::Impl::close ()
{
XUnmapWindow (xDisplay, xWindow);
}
//------------------------------------------------------------------------
void X11Window::Impl::onClose ()
{
XFreeGC (xDisplay, xGraphicContext);
XDestroyWindow (xDisplay, xWindow);
xDisplay = nullptr;
xWindow = 0;
isMapped = false;
if (windowClosedFunc)
windowClosedFunc (x11Window);
}
//------------------------------------------------------------------------
void X11Window::Impl::resize (Size newSize, bool force)
{
if (!force && mCurrentSize == newSize)
return;
if (xWindow)
XResizeWindow (xDisplay, xWindow, newSize.width, newSize.height);
if (plugParentWindow)
XResizeWindow (xDisplay, plugParentWindow, newSize.width, newSize.height);
mCurrentSize = newSize;
}
//------------------------------------------------------------------------
Size X11Window::Impl::getSize () const
{
::Window root;
int x, y;
unsigned int width, height;
unsigned int border_width;
unsigned int depth;
XGetGeometry (xDisplay, xWindow, &root, &x, &y, &width, &height, &border_width, &depth);
return {static_cast (width), static_cast (height)};
}
//------------------------------------------------------------------------
void X11Window::Impl::checkSize ()
{
if (getSize () != mCurrentSize)
{
resize (mCurrentSize, true);
}
}
//------------------------------------------------------------------------
bool X11Window::Impl::handleMainWindowEvent (const XEvent& event)
{
#if LOG_EVENTS
std::cout << "event " << event.type << "\n";
#endif
bool res = false;
switch (event.type)
{
case Expose:
if (event.xexpose.count == 0)
{
XClearWindow (xDisplay, xWindow);
XFillRectangle (xDisplay, xWindow, xGraphicContext, 0, 0, mCurrentSize.width,
mCurrentSize.height);
}
res = true;
break;
//--- StructureNotifyMask ------------------------------
// Window has been resized
case ConfigureNotify:
{
if (event.xconfigure.window != xWindow)
break;
auto width = event.xconfigure.width;
auto height = event.xconfigure.height;
Size size {width, height};
if (mCurrentSize != size)
{
auto constraintSize = controller->constrainSize (*x11Window, size);
if (constraintSize != mCurrentSize)
{
mCurrentSize = size;
controller->onResize (*x11Window, size);
}
if (constraintSize != size)
resize (constraintSize, true);
else
{
if (plugParentWindow)
XResizeWindow (xDisplay, plugParentWindow, size.width, size.height);
}
#if LOG_EVENTS
std::cout << "new size " << width << " x " << height << "\n";
#endif
}
res = true;
}
break;
// Window has been map to the screen
case MapNotify:
{
if (event.xany.window == xWindow && !isMapped)
{
controller->onShow (*x11Window);
isMapped = true;
res = true;
}
}
break;
case UnmapNotify:
{
if (event.xunmap.window == xWindow)
{
controller->onClose (*x11Window);
onClose ();
res = true;
}
break;
}
case DestroyNotify: break;
case ClientMessage:
{
if (event.xany.window == xWindow)
{
controller->onClose (*x11Window);
onClose ();
res = true;
}
break;
}
case FocusIn:
{
if (xembedInfo)
send_xembed_message (xDisplay, plugWindow, xEmbedAtom, XEMBED_WINDOW_ACTIVATE, 0,
plugParentWindow, xembedInfo->version);
break;
}
case FocusOut:
{
if (xembedInfo)
send_xembed_message (xDisplay, plugWindow, xEmbedAtom, XEMBED_WINDOW_DEACTIVATE, 0,
plugParentWindow, xembedInfo->version);
break;
}
//--- ResizeRedirectMask --------------------------------
case ResizeRequest:
{
if (event.xany.window == xWindow)
{
auto width = event.xresizerequest.width;
auto height = event.xresizerequest.height;
Size request {width, height};
if (mCurrentSize != request)
{
#if LOG_EVENTS
std::cout << "requested Size " << width << " x " << height << "\n";
#endif
auto constraintSize = controller->constrainSize (*x11Window, request);
if (constraintSize != request)
{
#if LOG_EVENTS
std::cout << "constraint Size " << constraintSize.width << " x "
<< constraintSize.height << "\n";
#endif
}
resize (constraintSize, true);
}
res = true;
}
}
break;
}
return res;
}
//------------------------------------------------------------------------
auto X11Window::Impl::getXEmbedInfo () -> XEmbedInfo*
{
int actualFormat;
unsigned long itemsReturned;
unsigned long bytesAfterReturn;
Atom actualType;
XEmbedInfo* xembedInfo = NULL;
if (xEmbedInfoAtom == None)
xEmbedInfoAtom = XInternAtom (xDisplay, "_XEMBED_INFO", true);
auto err =
XGetWindowProperty (xDisplay, plugWindow, xEmbedInfoAtom, 0, sizeof (xembedInfo), false,
xEmbedInfoAtom, &actualType, &actualFormat, &itemsReturned,
&bytesAfterReturn, reinterpret_cast (&xembedInfo));
if (err != Success)
return nullptr;
return xembedInfo;
}
//------------------------------------------------------------------------
bool X11Window::Impl::handlePlugEvent (const XEvent& event)
{
bool res = false;
switch (event.type)
{
// XEMBED specific
case ClientMessage:
{
auto name = XGetAtomName (xDisplay, event.xclient.message_type);
std::cout << name << std::endl;
if (event.xclient.message_type == xEmbedAtom)
{
switch (event.xclient.data.l[1])
{
case XEMBED_REQUEST_FOCUS:
{
send_xembed_message (xDisplay, plugWindow, xEmbedAtom, XEMBED_FOCUS_IN, 0,
plugParentWindow, xembedInfo->version);
break;
}
}
}
break;
}
case PropertyNotify:
{
auto name = XGetAtomName (xDisplay, event.xproperty.atom);
std::cout << name << std::endl;
if (event.xany.window == plugWindow)
{
if (event.xproperty.atom == xEmbedInfoAtom)
{
if (auto embedInfo = getXEmbedInfo ())
{
}
}
else
{
}
}
break;
}
case CreateNotify:
{
if (event.xcreatewindow.parent != plugParentWindow)
{
res = true;
break;
}
plugWindow = event.xcreatewindow.window;
xembedInfo = getXEmbedInfo ();
if (!xembedInfo)
{
std::cerr << "XGetWindowProperty for _XEMBED_INFO failed" << std::endl;
exit (-1);
}
if (xembedInfo->flags & XEMBED_MAPPED)
{
std::cerr << "Window already mapped error" << std::endl;
exit (-1);
}
RunLoop::instance ().registerWindow (
plugWindow, [this] (const XEvent& e) { return handlePlugEvent (e); });
// XSelectInput (xDisplay, plugWindow, PropertyChangeMask);
if (xEmbedAtom == None)
xEmbedAtom = XInternAtom (xDisplay, "_XEMBED", true);
assert (xEmbedAtom != None);
send_xembed_message (xDisplay, plugWindow, xEmbedAtom, XEMBED_EMBEDDED_NOTIFY, 0,
plugParentWindow, xembedInfo->version);
XMapWindow (xDisplay, plugWindow);
XResizeWindow (xDisplay, plugWindow, mCurrentSize.width, mCurrentSize.height);
// XSetInputFocus (xDisplay, plugWindow, RevertToParent, CurrentTime);
send_xembed_message (xDisplay, plugWindow, xEmbedAtom, XEMBED_WINDOW_ACTIVATE, 0,
plugParentWindow, xembedInfo->version);
send_xembed_message (xDisplay, plugWindow, xEmbedAtom, XEMBED_FOCUS_IN, 0,
plugParentWindow, xembedInfo->version);
XSync (xDisplay, False);
res = true;
break;
}
}
return res;
}
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/linux/window.h 0000664 0000000 0000000 00000007052 14615113443 0030434 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/platform/linux/window.h
// Created by : Steinberg 09.2016
// Description : Example of opening a plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/iwindow.h"
#include
struct _XDisplay;
typedef struct _XDisplay Display;
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace EditorHost {
//------------------------------------------------------------------------
class X11Window : public IWindow
{
public:
using Ptr = std::shared_ptr;
using WindowClosedFunc = std::function;
static Ptr make (const std::string& name, Size size, bool resizeable,
const WindowControllerPtr& controller, Display* display,
const WindowClosedFunc& windowClosedFunc);
X11Window ();
~X11Window () override;
bool init (const std::string& name, Size size, bool resizeable,
const WindowControllerPtr& controller, Display* display,
const WindowClosedFunc& windowClosedFunc);
void show () override;
void close () override;
void resize (Size newSize) override;
Size getContentSize () override;
NativePlatformWindow getNativePlatformWindow () const override;
tresult queryInterface (const TUID iid, void** obj) override;
void onIdle ();
private:
Size getSize () const;
struct Impl;
std::unique_ptr impl;
};
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/mac/ 0000775 0000000 0000000 00000000000 14615113443 0026351 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/mac/platform.mm 0000664 0000000 0000000 00000020446 14615113443 0030536 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/platform/mac/platform.mm
// Created by : Steinberg 09.2016
// Description : Example of opening a plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#import "public.sdk/samples/vst-hosting/editorhost/source/platform/iplatform.h"
#import "public.sdk/samples/vst-hosting/editorhost/source/platform/mac/window.h"
#import
#import
#if !__has_feature(objc_arc)
#error this file needs to be compiled with automatic reference counting enabled
#endif
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace EditorHost {
//------------------------------------------------------------------------
class Platform : public IPlatform
{
public:
static Platform& instance ()
{
static Platform gInstance;
return gInstance;
}
Platform ();
void setApplication (ApplicationPtr&& app) override;
WindowPtr createWindow (const std::string& title, Size size, bool resizeable,
const WindowControllerPtr& controller) override;
void quit () override;
void kill (int resultCode, const std::string& reason) override;
FUnknown* getPluginFactoryContext () override;
ApplicationPtr application;
bool quitRequested {false};
};
//------------------------------------------------------------------------
Platform::Platform ()
{
NSApplicationLoad ();
}
//------------------------------------------------------------------------
void Platform::setApplication (ApplicationPtr&& app)
{
application = std::move (app);
}
//------------------------------------------------------------------------
WindowPtr Platform::createWindow (const std::string& title, Size size, bool resizeable,
const WindowControllerPtr& controller)
{
return Window::make (title, size, resizeable, controller);
}
//------------------------------------------------------------------------
void Platform::quit ()
{
if (quitRequested)
return;
quitRequested = true;
dispatch_after (dispatch_time (DISPATCH_TIME_NOW, (int64_t) (0.1 * NSEC_PER_SEC)),
dispatch_get_main_queue (), ^{
@autoreleasepool
{
for (NSWindow* window in NSApp.windows)
[window close];
}
application = nullptr;
[NSApp terminate:nil];
});
}
//------------------------------------------------------------------------
void Platform::kill (int resultCode, const std::string& reason)
{
std::cout << reason << "\n";
std::cout.flush ();
auto alert = [NSAlert new];
alert.messageText = [NSString stringWithUTF8String:reason.data ()];
alert.alertStyle = NSCriticalAlertStyle;
[alert addButtonWithTitle:@"Quit"];
[alert runModal];
exit (resultCode);
}
//------------------------------------------------------------------------
FUnknown* Platform::getPluginFactoryContext ()
{
return nullptr;
}
//------------------------------------------------------------------------
IPlatform& IPlatform::instance ()
{
return Platform::instance ();
}
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
//------------------------------------------------------------------------
@interface VSTSDK_AppDelegate : NSObject
{
std::vector cmdArgs;
}
@end
//------------------------------------------------------------------------
@implementation VSTSDK_AppDelegate
//------------------------------------------------------------------------
- (void)setCmdArgs:(std::vector&&)args
{
cmdArgs = std::move (args);
}
//------------------------------------------------------------------------
- (NSMenu*)createAppMenu
{
auto appName =
static_cast ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"]);
NSMenu* menu = [[NSMenu alloc] initWithTitle:appName];
[menu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName]
action:@selector (hide:)
keyEquivalent:@"h"];
[menu addItemWithTitle:@"Hide Others"
action:@selector (hideOtherApplications:)
keyEquivalent:@""];
[menu addItemWithTitle:@"Show All" action:@selector (unhideAllApplications:) keyEquivalent:@""];
[menu addItem:[NSMenuItem separatorItem]];
[menu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", appName]
action:@selector (terminate:)
keyEquivalent:@"q"];
return menu;
}
//------------------------------------------------------------------------
- (NSMenu*)createFileMenu
{
NSMenu* menu = [[NSMenu alloc] initWithTitle:@"File"];
[menu addItemWithTitle:@"Close Window" action:@selector (performClose:) keyEquivalent:@"w"];
return menu;
}
//------------------------------------------------------------------------
- (void)setupMenubar
{
auto mainMenu = [NSMenu new];
[NSApp setMainMenu:mainMenu];
auto appMenuItem = [[NSMenuItem alloc] initWithTitle:@"App" action:nil keyEquivalent:@""];
[mainMenu addItem:appMenuItem];
appMenuItem.submenu = [self createAppMenu];
auto fileMenuItem = [[NSMenuItem alloc] initWithTitle:@"File" action:nil keyEquivalent:@""];
[mainMenu addItem:fileMenuItem];
fileMenuItem.submenu = [self createFileMenu];
}
//------------------------------------------------------------------------
- (BOOL)application:(NSApplication*)sender openFile:(NSString*)filename
{
if (cmdArgs.empty ())
cmdArgs.push_back ([filename UTF8String]);
return YES;
}
//------------------------------------------------------------------------
- (void)applicationDidFinishLaunching:(NSNotification*)notification
{
[self setupMenubar];
Steinberg::Vst::EditorHost::Platform::instance ().application->init (cmdArgs);
cmdArgs.clear ();
}
//------------------------------------------------------------------------
- (void)applicationWillTerminate:(NSNotification*)notification
{
if (auto& app = Steinberg::Vst::EditorHost::Platform::instance ().application)
app->terminate ();
}
@end
//------------------------------------------------------------------------
int main (int argc, const char* argv[])
{
auto delegate = [VSTSDK_AppDelegate new];
std::vector cmdArgs;
for (int i = 1; i < argc; ++i)
cmdArgs.push_back (argv[i]);
[delegate setCmdArgs:std::move (cmdArgs)];
[NSApplication sharedApplication].delegate = delegate;
return NSApplicationMain (argc, argv);
}
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/mac/window.h 0000664 0000000 0000000 00000006515 14615113443 0030040 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/platform/mac/window.h
// Created by : Steinberg 09.2016
// Description : Example of opening a plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/iwindow.h"
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace EditorHost {
//------------------------------------------------------------------------
class Window : public IWindow, public std::enable_shared_from_this
{
public:
static WindowPtr make (const std::string& name, Size size, bool resizeable,
const WindowControllerPtr& controller);
Window ();
~Window () noexcept override;
bool init (const std::string& name, Size size, bool resizeable,
const WindowControllerPtr& controller);
void show () override;
void close () override;
void resize (Size newSize) override;
Size getContentSize () override;
NativePlatformWindow getNativePlatformWindow () const override;
tresult queryInterface (const TUID iid, void** obj) override { return kNoInterface; }
WindowControllerPtr getController () const;
void windowClosed ();
private:
struct Impl;
std::unique_ptr impl;
};
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/mac/window.mm 0000664 0000000 0000000 00000020222 14615113443 0030211 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/platform/mac/window.mm
// Created by : Steinberg 09.2016
// Description : Example of opening a plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#import "public.sdk/samples/vst-hosting/editorhost/source/platform/mac/window.h"
#import
#if !__has_feature(objc_arc)
#error this file needs to be compiled with automatic reference counting enabled
#endif
using namespace Steinberg::Vst;
//------------------------------------------------------------------------
@interface VSTSDK_WindowDelegate : NSObject
#if __i386__
{
std::shared_ptr _window;
NSWindow* _nsWindow;
}
#endif
@property (readonly) std::shared_ptr window;
@property (strong, readwrite) NSWindow* nsWindow;
- (id)initWithWindow:(std::shared_ptr)window;
@end
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace EditorHost {
//------------------------------------------------------------------------
struct Window::Impl
{
WindowControllerPtr controller;
VSTSDK_WindowDelegate* nsWindowDelegate {nullptr};
};
//------------------------------------------------------------------------
WindowPtr Window::make (const std::string& name, Size size, bool resizeable,
const WindowControllerPtr& controller)
{
auto window = std::make_shared ();
if (window->init (name, size, resizeable, controller))
return window;
return nullptr;
}
//------------------------------------------------------------------------
Window::Window ()
{
impl = std::unique_ptr (new Impl);
}
//------------------------------------------------------------------------
bool Window::init (const std::string& name, Size size, bool resizeable,
const WindowControllerPtr& controller)
{
impl->controller = controller;
NSUInteger styleMask = NSTitledWindowMask | NSClosableWindowMask;
if (resizeable)
styleMask |= NSResizableWindowMask;
auto contentRect =
NSMakeRect (0., 0., static_cast (size.width), static_cast (size.height));
impl->nsWindowDelegate = [[VSTSDK_WindowDelegate alloc] initWithWindow:shared_from_this ()];
auto nsWindow = [[NSWindow alloc] initWithContentRect:contentRect
styleMask:styleMask
backing:NSBackingStoreBuffered
defer:YES];
[nsWindow setDelegate:impl->nsWindowDelegate];
nsWindow.releasedWhenClosed = NO;
impl->nsWindowDelegate.nsWindow = nsWindow;
[nsWindow center];
return true;
}
//------------------------------------------------------------------------
Window::~Window () noexcept
{
}
//------------------------------------------------------------------------
void Window::show ()
{
auto nsWindow = impl->nsWindowDelegate.nsWindow;
impl->controller->onShow (*this);
[nsWindow makeKeyAndOrderFront:nil];
}
//------------------------------------------------------------------------
void Window::close ()
{
auto nsWindow = impl->nsWindowDelegate.nsWindow;
[nsWindow close];
}
//------------------------------------------------------------------------
void Window::resize (Size newSize)
{
auto nsWindow = impl->nsWindowDelegate.nsWindow;
auto r = [nsWindow contentRectForFrameRect:nsWindow.frame];
auto diff = newSize.height - r.size.height;
r.size.width = newSize.width;
r.size.height = newSize.height;
r.origin.y -= diff;
[nsWindow setFrame:[nsWindow frameRectForContentRect:r]
display:[nsWindow isVisible]
animate:NO];
}
//------------------------------------------------------------------------
Size Window::getContentSize ()
{
auto nsWindow = impl->nsWindowDelegate.nsWindow;
auto r = [nsWindow contentRectForFrameRect:nsWindow.frame];
return {static_cast (r.size.width), static_cast (r.size.height)};
}
//------------------------------------------------------------------------
NativePlatformWindow Window::getNativePlatformWindow () const
{
auto nsWindow = impl->nsWindowDelegate.nsWindow;
return {kPlatformTypeNSView, (__bridge void*)([nsWindow contentView])};
}
//------------------------------------------------------------------------
WindowControllerPtr Window::getController () const
{
return impl->controller;
}
//------------------------------------------------------------------------
void Window::windowClosed ()
{
impl->controller->onClose (*this);
impl->nsWindowDelegate = nullptr;
}
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
//------------------------------------------------------------------------
@implementation VSTSDK_WindowDelegate
#if __i386__
@synthesize window = _window;
#endif
//------------------------------------------------------------------------
- (id)initWithWindow:(std::shared_ptr)window
{
if (self = [super init])
{
self->_window = window;
}
return self;
}
//------------------------------------------------------------------------
- (NSSize)windowWillResize:(nonnull NSWindow*)sender toSize:(NSSize)frameSize
{
NSRect r {};
r.size = frameSize;
r = [sender contentRectForFrameRect:r];
EditorHost::Size size {static_cast (r.size.width),
static_cast (r.size.height)};
size = self.window->getController ()->constrainSize (*self.window, size);
r.size.width = size.width;
r.size.height = size.height;
r = [sender frameRectForContentRect:r];
return r.size;
}
//------------------------------------------------------------------------
- (void)windowDidResize:(nonnull NSNotification*)notification
{
NSWindow* window = [notification object];
NSRect r = window.frame;
r = [window contentRectForFrameRect:r];
EditorHost::Size size {static_cast (r.size.width),
static_cast (r.size.height)};
self.window->getController ()->onResize (*self.window, size);
}
//------------------------------------------------------------------------
- (void)windowWillClose:(nonnull NSNotification*)notification
{
self.window->windowClosed ();
self->_window = nullptr;
self->_nsWindow = nullptr;
}
@end
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/win32/ 0000775 0000000 0000000 00000000000 14615113443 0026553 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/win32/platform.cpp 0000664 0000000 0000000 00000014046 14615113443 0031110 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/platform/win32/platform.cpp
// Created by : Steinberg 09.2016
// Description : Example of opening a plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/iplatform.h"
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/win32/window.h"
#include "public.sdk/source/vst/utility/stringconvert.h"
#include "pluginterfaces/base/ftypes.h"
#include
#include
#include
#include
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace EditorHost {
//------------------------------------------------------------------------
class Platform : public IPlatform
{
public:
static Platform& instance ()
{
static Platform gInstance;
return gInstance;
}
void setApplication (ApplicationPtr&& app) override;
WindowPtr createWindow (const std::string& title, Size size, bool resizeable,
const WindowControllerPtr& controller) override;
void quit () override;
void kill (int resultCode, const std::string& reason) override;
FUnknown* getPluginFactoryContext () override;
void run (LPWSTR lpCmdLine, HINSTANCE instance);
private:
ApplicationPtr application;
HINSTANCE hInstance {nullptr};
bool quitRequested {false};
};
//------------------------------------------------------------------------
IPlatform& IPlatform::instance ()
{
return Platform::instance ();
}
//------------------------------------------------------------------------
void Platform::setApplication (ApplicationPtr&& app)
{
application = std::move (app);
}
//------------------------------------------------------------------------
WindowPtr Platform::createWindow (const std::string& title, Size size, bool resizeable,
const WindowControllerPtr& controller)
{
return Window::make (title, size, resizeable, controller, hInstance);
}
//------------------------------------------------------------------------
void Platform::quit ()
{
if (quitRequested)
return;
quitRequested = true;
for (auto& window : Window::getWindows ())
window->closeImmediately ();
if (application)
application->terminate ();
PostQuitMessage (0);
}
//------------------------------------------------------------------------
void Platform::kill (int resultCode, const std::string& reason)
{
auto str = VST3::StringConvert::convert (reason);
MessageBox (nullptr, reinterpret_cast (str.data ()), nullptr, MB_OK);
exit (resultCode);
}
//------------------------------------------------------------------------
FUnknown* Platform::getPluginFactoryContext ()
{
return nullptr;
}
//------------------------------------------------------------------------
void Platform::run (LPWSTR lpCmdLine, HINSTANCE _hInstance)
{
hInstance = _hInstance;
std::vector cmdArgStrings;
int numArgs = 0;
auto cmdArgsArray = CommandLineToArgvW (lpCmdLine, &numArgs);
cmdArgStrings.reserve (numArgs);
for (int i = 0; i < numArgs; ++i)
{
cmdArgStrings.push_back (
VST3::StringConvert::convert (Steinberg::wscast (cmdArgsArray[i])));
}
LocalFree (cmdArgsArray);
auto noHIDPI = std::find (cmdArgStrings.begin (), cmdArgStrings.end (), "-noHIDPI");
if (noHIDPI == cmdArgStrings.end ())
ShcoreLibrary::instance ().setProcessDpiAwareness (true);
application->init (cmdArgStrings);
MSG msg;
while (GetMessage (&msg, nullptr, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
#ifndef _In_
#define _In_
#endif
#ifndef _In_opt_
#define _In_opt_
#endif
//------------------------------------------------------------------------
int APIENTRY wWinMain (_In_ HINSTANCE instance, _In_opt_ HINSTANCE /*prevInstance*/,
_In_ LPWSTR lpCmdLine, _In_ int /*nCmdShow*/)
{
HRESULT hr = CoInitialize (nullptr);
if (FAILED (hr))
return FALSE;
Steinberg::Vst::EditorHost::Platform::instance ().run (lpCmdLine, instance);
CoUninitialize ();
return 0;
}
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/win32/window.cpp 0000664 0000000 0000000 00000025041 14615113443 0030570 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/platform/win32/window.cpp
// Created by : Steinberg 09.2016
// Description : Example of opening a plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#include "window.h"
#include "public.sdk/source/vst/utility/stringconvert.h"
#include
#ifndef WM_DPICHANGED
#define WM_DPICHANGED 0x02E0
#endif
#ifndef WM_GETDPISCALEDSIZE
#define WM_GETDPISCALEDSIZE 0x02E4
#endif
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace EditorHost {
//------------------------------------------------------------------------
namespace {
static Window::WindowList gAllWindows;
//------------------------------------------------------------------------
static void addWindow (Window* window)
{
gAllWindows.push_back (window);
}
//------------------------------------------------------------------------
static void removeWindow (Window* window)
{
auto it = std::find (gAllWindows.begin (), gAllWindows.end (), window);
if (it != gAllWindows.end ())
gAllWindows.erase (it);
}
//------------------------------------------------------------------------
} // anonymous
//------------------------------------------------------------------------
static const WCHAR* gWindowClassName = L"VSTSDK WindowClass";
//------------------------------------------------------------------------
WindowPtr Window::make (const std::string& name, Size size, bool resizeable,
const WindowControllerPtr& controller, HINSTANCE instance)
{
auto window = std::make_shared ();
if (window->init (name, size, resizeable, controller, instance))
return window;
return nullptr;
}
//------------------------------------------------------------------------
LRESULT CALLBACK Window::WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
auto* window = reinterpret_cast ((LONG_PTR)GetWindowLongPtr (hWnd, GWLP_USERDATA));
if (window)
return window->proc (message, wParam, lParam);
return DefWindowProc (hWnd, message, wParam, lParam);
}
//------------------------------------------------------------------------
void Window::registerWindowClass (HINSTANCE instance)
{
static bool once = true;
if (!once)
return;
once = true;
WNDCLASSEX wcex {};
wcex.cbSize = sizeof (WNDCLASSEX);
wcex.style = CS_DBLCLKS;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = instance;
wcex.hCursor = LoadCursor (instance, IDC_ARROW);
wcex.hbrBackground = nullptr;
wcex.lpszClassName = gWindowClassName;
RegisterClassEx (&wcex);
}
//------------------------------------------------------------------------
auto Window::getWindows () -> WindowList
{
return gAllWindows;
}
//------------------------------------------------------------------------
bool Window::init (const std::string& name, Size size, bool resizeable,
const WindowControllerPtr& _controller, HINSTANCE instance)
{
controller = _controller;
registerWindowClass (instance);
DWORD exStyle = WS_EX_APPWINDOW;
DWORD dwStyle = WS_CAPTION | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
if (resizeable)
dwStyle |= WS_SIZEBOX | WS_MAXIMIZEBOX;
auto windowTitle = VST3::StringConvert::convert (name);
RECT rect {0, 0, size.width, size.height};
AdjustWindowRectEx (&rect, dwStyle, false, exStyle);
hwnd = CreateWindowEx (exStyle, gWindowClassName, (const TCHAR*)windowTitle.data (), dwStyle, 0,
0, rect.right - rect.left, rect.bottom - rect.top, nullptr, nullptr,
instance, nullptr);
if (hwnd)
{
SetWindowLongPtr (hwnd, GWLP_USERDATA, (__int3264) (LONG_PTR)this);
This = shared_from_this ();
addWindow (this);
}
return hwnd != nullptr;
}
//------------------------------------------------------------------------
LRESULT Window::proc (UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_ERASEBKGND:
{
return TRUE; // do not draw background
}
case WM_PAINT:
{
PAINTSTRUCT ps {};
BeginPaint (hwnd, &ps);
EndPaint (hwnd, &ps);
return FALSE;
}
case WM_SIZE:
{
controller->onResize (*this, getContentSize ());
break;
}
case WM_SIZING:
{
auto* newSize = reinterpret_cast (lParam);
RECT oldSize;
GetWindowRect (hwnd, &oldSize);
RECT clientSize;
GetClientRect (hwnd, &clientSize);
auto diffX = (newSize->right - newSize->left) - (oldSize.right - oldSize.left);
auto diffY = (newSize->bottom - newSize->top) - (oldSize.bottom - oldSize.top);
Size newClientSize = {(clientSize.right - clientSize.left),
(clientSize.bottom - clientSize.top)};
newClientSize.width += diffX;
newClientSize.height += diffY;
auto constraintSize = controller->constrainSize (*this, newClientSize);
if (constraintSize != newClientSize)
{
auto diffX2 = (oldSize.right - oldSize.left) - (clientSize.right - clientSize.left);
auto diffY2 = (oldSize.bottom - oldSize.top) - (clientSize.bottom - clientSize.top);
newSize->right = newSize->left + static_cast (constraintSize.width + diffX2);
newSize->bottom = newSize->top + static_cast (constraintSize.height + diffY2);
}
return TRUE;
}
case WM_CLOSE:
{
closeImmediately ();
return TRUE;
}
case WM_GETDPISCALEDSIZE:
{
inDpiChangeState = true;
auto* proposedSize = reinterpret_cast (lParam);
auto newScaleFactor =
static_cast (wParam) / static_cast (USER_DEFAULT_SCREEN_DPI);
controller->onContentScaleFactorChanged (*this, newScaleFactor);
if (dpiChangedSize.width != 0 && dpiChangedSize.height != 0)
{
WINDOWINFO windowInfo {0};
GetWindowInfo (hwnd, &windowInfo);
RECT clientRect {};
clientRect.right = dpiChangedSize.width;
clientRect.bottom = dpiChangedSize.height;
User32Library::instance ().adjustWindowRectExForDpi (
&clientRect, windowInfo.dwStyle, false, windowInfo.dwExStyle, wParam);
proposedSize->cx = clientRect.right - clientRect.left;
proposedSize->cy = clientRect.bottom - clientRect.top;
return TRUE;
}
return FALSE;
}
case WM_DPICHANGED:
{
if (inDpiChangeState)
{
auto* rect = reinterpret_cast (lParam);
inDpiChangeState = false;
dpiChangedSize = {};
SetWindowPos (hwnd, nullptr, rect->left, rect->top, rect->right - rect->left,
rect->bottom - rect->top, SWP_NOZORDER | SWP_NOACTIVATE);
return 0;
}
controller->onContentScaleFactorChanged (*this, getContentScaleFactor ());
return 0;
}
}
return DefWindowProc (hwnd, message, wParam, lParam);
}
//------------------------------------------------------------------------
void Window::closeImmediately ()
{
close ();
removeWindow (this);
controller->onClose (*this);
SetWindowLongPtr (hwnd, GWLP_USERDATA, (__int3264) (LONG_PTR) nullptr);
This = nullptr;
}
//------------------------------------------------------------------------
Size Window::getContentSize ()
{
RECT r;
GetClientRect (hwnd, &r);
return {r.right - r.left, r.bottom - r.top};
}
//------------------------------------------------------------------------
float Window::getContentScaleFactor () const
{
if (auto dpiForWindow = ShcoreLibrary::instance ().getDpiForWindow (hwnd))
{
return static_cast (dpiForWindow->x) / static_cast (USER_DEFAULT_SCREEN_DPI);
}
return 1.f;
}
//------------------------------------------------------------------------
void Window::show ()
{
controller->onContentScaleFactorChanged (*this, getContentScaleFactor ());
controller->onShow (*this);
SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOCOPYBITS | SWP_SHOWWINDOW);
}
//------------------------------------------------------------------------
void Window::close ()
{
ShowWindow (hwnd, false);
}
//------------------------------------------------------------------------
void Window::resize (Size newSize)
{
if (inDpiChangeState)
{
dpiChangedSize = newSize;
return;
}
if (getContentSize () == newSize)
return;
WINDOWINFO windowInfo {0};
GetWindowInfo (hwnd, &windowInfo);
RECT clientRect {};
clientRect.right = newSize.width;
clientRect.bottom = newSize.height;
AdjustWindowRectEx (&clientRect, windowInfo.dwStyle, false, windowInfo.dwExStyle);
SetWindowPos (hwnd, HWND_TOP, 0, 0, clientRect.right - clientRect.left,
clientRect.bottom - clientRect.top, SWP_NOMOVE | SWP_NOCOPYBITS | SWP_NOACTIVATE);
}
//------------------------------------------------------------------------
NativePlatformWindow Window::getNativePlatformWindow () const
{
return {kPlatformTypeHWND, hwnd};
}
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/platform/win32/window.h 0000664 0000000 0000000 00000017413 14615113443 0030241 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/platform/win32/window.h
// Created by : Steinberg 09.2016
// Description : Example of opening a plug-in editor
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include "public.sdk/samples/vst-hosting/editorhost/source/platform/iwindow.h"
#include "public.sdk/source/vst/utility/optional.h"
#include
#include
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace EditorHost {
//------------------------------------------------------------------------
class Window : public IWindow, public std::enable_shared_from_this
{
public:
static WindowPtr make (const std::string& name, Size size, bool resizeable,
const WindowControllerPtr& controller, HINSTANCE instance);
bool init (const std::string& name, Size size, bool resizeable,
const WindowControllerPtr& controller, HINSTANCE instance);
void show () override;
void close () override;
void resize (Size newSize) override;
Size getContentSize () override;
NativePlatformWindow getNativePlatformWindow () const override;
tresult queryInterface (const TUID /*iid*/, void** /*obj*/) override { return kNoInterface; }
void closeImmediately ();
using WindowList = std::vector;
static WindowList getWindows ();
private:
LRESULT CALLBACK proc (UINT message, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
float getContentScaleFactor () const;
void registerWindowClass (HINSTANCE instance);
WindowPtr This;
WindowControllerPtr controller {nullptr};
HWND hwnd {nullptr};
bool inDpiChangeState {false};
Size dpiChangedSize {};
};
//------------------------------------------------------------------------
struct DynamicLibrary
{
DynamicLibrary (const char* name) { module = LoadLibraryA (name); }
~DynamicLibrary () { FreeLibrary (module); }
template
T getProcAddress (const char* name)
{
return module ? reinterpret_cast (GetProcAddress (module, name)) : nullptr;
}
private:
HMODULE module {nullptr};
};
#ifndef _DPI_AWARENESS_CONTEXTS_
DECLARE_HANDLE (DPI_AWARENESS_CONTEXT);
typedef enum DPI_AWARENESS {
DPI_AWARENESS_INVALID = -1,
DPI_AWARENESS_UNAWARE = 0,
DPI_AWARENESS_SYSTEM_AWARE = 1,
DPI_AWARENESS_PER_MONITOR_AWARE = 2
} DPI_AWARENESS;
#define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT)-1)
#define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((DPI_AWARENESS_CONTEXT)-2)
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT)-3)
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT)-4)
#endif
struct User32Library : DynamicLibrary
{
static User32Library& instance ()
{
static User32Library gInstance;
return gInstance;
}
bool setProcessDpiAwarenessContext (DPI_AWARENESS_CONTEXT context) const
{
if (!setProcessDpiAwarenessContextProc)
return false;
return setProcessDpiAwarenessContextProc (context);
}
bool adjustWindowRectExForDpi (LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle,
UINT dpi) const
{
if (!adjustWindowRectExForDpiProc)
return false;
return adjustWindowRectExForDpiProc (lpRect, dwStyle, bMenu, dwExStyle, dpi);
}
private:
using SetProcessDpiAwarenessContextProc = BOOL (WINAPI*) (DPI_AWARENESS_CONTEXT);
using AdjustWindowRectExForDpiProc = BOOL (WINAPI*) (LPRECT, DWORD, BOOL, DWORD, UINT);
User32Library () : DynamicLibrary ("User32.dll")
{
setProcessDpiAwarenessContextProc =
getProcAddress ("SetProcessDpiAwarenessContext");
adjustWindowRectExForDpiProc =
getProcAddress ("AdjustWindowRectExForDpi");
}
SetProcessDpiAwarenessContextProc setProcessDpiAwarenessContextProc {nullptr};
AdjustWindowRectExForDpiProc adjustWindowRectExForDpiProc {nullptr};
};
struct ShcoreLibrary : DynamicLibrary
{
static ShcoreLibrary& instance ()
{
static ShcoreLibrary gInstance;
return gInstance;
}
struct DPI
{
UINT x;
UINT y;
};
VST3::Optional getDpiForWindow (HWND window) const
{
if (!getDpiForMonitorProc)
return {};
auto monitor = MonitorFromWindow (window, MONITOR_DEFAULTTONEAREST);
UINT x, y;
getDpiForMonitorProc (monitor, MDT_EFFECTIVE_DPI, &x, &y);
return DPI {x, y};
}
HRESULT setProcessDpiAwareness (bool perMonitor = true)
{
if (perMonitor)
{
if (User32Library::instance ().setProcessDpiAwarenessContext (
perMonitor ? DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 :
DPI_AWARENESS_CONTEXT_UNAWARE))
return true;
}
if (!setProcessDpiAwarenessProc)
return S_FALSE;
return setProcessDpiAwarenessProc (perMonitor ? PROCESS_PER_MONITOR_DPI_AWARE :
PROCESS_SYSTEM_DPI_AWARE);
}
private:
enum PROCESS_DPI_AWARENESS
{
PROCESS_DPI_UNAWARE = 0,
PROCESS_SYSTEM_DPI_AWARE = 1,
PROCESS_PER_MONITOR_DPI_AWARE = 2
};
enum MONITOR_DPI_TYPE
{
MDT_EFFECTIVE_DPI = 0,
MDT_ANGULAR_DPI = 1,
MDT_RAW_DPI = 2,
MDT_DEFAULT = MDT_EFFECTIVE_DPI
};
using GetDpiForMonitorProc = HRESULT (WINAPI*) (HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*);
using SetProcessDpiAwarenessProc = HRESULT (WINAPI*) (PROCESS_DPI_AWARENESS);
ShcoreLibrary () : DynamicLibrary ("Shcore.dll")
{
getDpiForMonitorProc = getProcAddress ("GetDpiForMonitor");
setProcessDpiAwarenessProc =
getProcAddress ("SetProcessDpiAwareness");
}
GetDpiForMonitorProc getDpiForMonitorProc {nullptr};
SetProcessDpiAwarenessProc setProcessDpiAwarenessProc {nullptr};
};
#ifndef DPI_ENUMS_DECLARED
#define DPI_ENUMS_DECLARED
#endif // (DPI_ENUMS_DECLARED)
//------------------------------------------------------------------------
} // EditorHost
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/editorhost/source/usediids.cpp 0000664 0000000 0000000 00000004751 14615113443 0026311 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format auto
// Project : VST SDK
//
// Category : EditorHost
// Filename : public.sdk/samples/vst-hosting/editorhost/source/usediids.cpp
// Created by : Steinberg 09.2008
// Description : Interface symbols file
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
//#define INIT_CLASS_IID
// This macro definition modifies the behavior of DECLARE_CLASS_IID (funknown.h)
// and produces the actual symbols for all interface identifiers.
// It must be defined before including the interface headers and
// in only one source file!
//------------------------------------------------------------------------
//#define INIT_CLASS_IID
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/inspectorapp/ 0000775 0000000 0000000 00000000000 14615113443 0023010 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/inspectorapp/CMakeLists.txt 0000664 0000000 0000000 00000005503 14615113443 0025553 0 ustar 00root root 0000000 0000000
if(SMTG_ENABLE_VST3_HOSTING_EXAMPLES AND TARGET vstgui AND TARGET vstgui_standalone)
##########################################################################################
set(target VST3Inspector)
##########################################################################################
set(${target}_sources
"source/app.cpp"
"source/window.cpp"
"source/window.h"
"${SDK_ROOT}/pluginterfaces/base/coreiids.cpp"
"${SDK_ROOT}/public.sdk/source/vst/hosting/module.h"
"${SDK_ROOT}/public.sdk/source/vst/hosting/module.cpp"
"${SDK_ROOT}/public.sdk/source/vst/utility/stringconvert.h"
"${SDK_ROOT}/public.sdk/source/vst/utility/stringconvert.cpp"
"${SDK_ROOT}/public.sdk/source/vst/moduleinfo/moduleinfoparser.cpp"
"${SDK_ROOT}/public.sdk/source/vst/moduleinfo/moduleinfocreator.cpp"
)
set(${target}_resources
"resource/window.uidesc"
)
##########################################################################################
if(SMTG_MAC)
set(${target}_sources
${${target}_sources}
"${SDK_ROOT}/public.sdk/source/vst/hosting/module_mac.mm"
)
set_source_files_properties(
"${SDK_ROOT}/public.sdk/source/vst/hosting/module_mac.mm" PROPERTIES
COMPILE_FLAGS "-fobjc-arc"
)
elseif(SMTG_WIN)
set(${target}_sources
${${target}_sources}
"${SDK_ROOT}/public.sdk/source/vst/hosting/module_win32.cpp"
)
elseif(SMTG_LINUX)
set(${target}_sources
${${target}_sources}
"${SDK_ROOT}/public.sdk/source/vst/hosting/module_linux.cpp"
)
endif(SMTG_MAC)
##########################################################################################
# 'vstgui_add_executable' links both targets 'vstgui' and 'vstgui_standalone' to 'VST3Inspector'
vstgui_add_executable(${target} "${${target}_sources}")
vstgui_set_target_bundle_id(${target} "com.steinberg.vstsdk.vst3inspector")
if(NOT SMTG_MAC)
set_target_properties(${target}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$<$:bin/Debug>$<$:bin/Release>$<$:bin/ReleaseLTO>/VST3Inspector
)
endif(NOT SMTG_MAC)
vstgui_add_resources(${target} "${${target}_resources}")
vstgui_set_target_infoplist(${target} "resource/Info.plist")
#vstgui_set_cxx_version(${target} 17)
target_include_directories(${target}
PRIVATE
"${SMTG_VSTGUI_SOURCE_DIR}/"
"${SDK_ROOT}"
)
if(SDK_IDE_HOSTING_EXAMPLES_FOLDER)
set_target_properties(${target}
PROPERTIES
${SDK_IDE_HOSTING_EXAMPLES_FOLDER}
)
endif(SDK_IDE_HOSTING_EXAMPLES_FOLDER)
endif()
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/inspectorapp/resource/ 0000775 0000000 0000000 00000000000 14615113443 0024637 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/inspectorapp/resource/Info.plist 0000664 0000000 0000000 00000001542 14615113443 0026611 0 ustar 00root root 0000000 0000000
CFBundleDevelopmentRegion
en
CFBundleExecutable
${EXECUTABLE}
CFBundleIdentifier
com.steinberg.vstsdk.vst3inspector
CFBundleInfoDictionaryVersion
6.0
CFBundleName
VST3Inspector
CFBundlePackageType
BNDL
CFBundleShortVersionString
1.0.0
CFBundleVersion
1
NSHumanReadableCopyright
Copyright © 2021 Steinberg Media Technologies. All rights reserved.
NSPrincipalClass
NSApplication
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/inspectorapp/resource/window.uidesc 0000664 0000000 0000000 00000135367 14615113443 0027363 0 ustar 00root root 0000000 0000000 {
"vstgui-ui-description": {
"version": "1",
"bitmaps": {},
"fonts": {
"list": {
"font-name": "Arial",
"size": "12"
}
},
"colors": {
"focus": "#698ecbce",
"group.background": "#00000020",
"group.frame": "#000000ff",
"list.background": "#2a2e31ff",
"list.background.selected": "#155a8eff",
"list.frame": "#151719ff",
"list.text": "#ffffffff",
"list.text.selected": "#ffffffff",
"scrollbar.background": "#ffffff4b",
"scrollbar.frame": "#ffffff00",
"scrollbar.scroller": "#000000ff",
"window.background": "#1f1f24ff"
},
"gradients": {},
"control-tags": {
"ClassInfo::Cardinality": "14",
"ClassInfo::Category": "8",
"ClassInfo::ClassFlags": "15",
"ClassInfo::ClassID": "7",
"ClassInfo::Name": "9",
"ClassInfo::SDKVersion": "12",
"ClassInfo::SubCategories": "13",
"ClassInfo::Vendor": "10",
"ClassInfo::Version": "11",
"ClassInfoList": "6",
"Factory::EMail": "4",
"Factory::Flags": "5",
"Factory::URL": "3",
"Factory::Vendor": "2",
"Module::Path": "1",
"ModulePathList": "0"
},
"custom": {
"UIDescFilePath": {
"path": "/Volumes/DevPluginSet/DevPluginSet/public.sdk/samples/vst-hosting/inspectorapp/resource/window.uidesc"
},
"UIGridController": {
"Grids": "1x 1,5x 5,10x 10,12x 12,15x 15",
"Size": "5, 5"
},
"UITemplateController": {
"SelectedTemplate": "MainWindow"
},
"UIEditController": {
"EditViewScale": "1",
"EditorSize": "0, 0, 1403, 1036",
"SplitViewSize_0_0": "0.7633663366336633782083254118333570659161",
"SplitViewSize_0_1": "0.2168316831683168299793607047831756062806",
"SplitViewSize_1_0": "0.4881188118811881082592663005925714969635",
"SplitViewSize_1_1": "0.5089108910891089188055502745555713772774",
"SplitViewSize_2_0": "0.7954383464005702064625324965163599699736",
"SplitViewSize_2_1": "0.2009978617248752708057679683406604453921",
"TabSwitchValue": "2",
"Version": "1"
},
"UIAttributesController": {},
"UIViewCreatorDataSource": {
"SelectedRow": "29"
},
"UIBitmapsDataSource": {
"SelectedRow": "-1"
},
"UIGradientsDataSource": {
"SelectedRow": "-1"
},
"UIColorsDataSource": {
"SelectedRow": "0"
},
"UIFontsDataSource": {
"SelectedRow": "0"
},
"UITagsDataSource": {
"SelectedRow": "-1"
},
"FocusDrawing": {
"color": "focus",
"enabled": "true",
"width": "1.5"
}
},
"templates": {
"MainWindow": {
"attributes": {
"autosize": "left right top bottom ",
"background-color": "window.background",
"background-color-draw-style": "filled and stroked",
"class": "CViewContainer",
"minSize": "755, 605",
"mouse-enabled": "true",
"opacity": "1",
"origin": "0, 0",
"size": "755, 605",
"transparent": "false",
"wants-focus": "false"
},
"children": {
"CScrollView": {
"attributes": {
"auto-drag-scrolling": "false",
"auto-hide-scrollbars": "true",
"autosize": "left top bottom ",
"background-color": "list.background",
"background-color-draw-style": "filled and stroked",
"bordered": "false",
"class": "CScrollView",
"container-size": "182, 1872",
"follow-focus-view": "false",
"horizontal-scrollbar": "false",
"mouse-enabled": "true",
"opacity": "1",
"origin": "10, 30",
"overlay-scrollbars": "false",
"scrollbar-background-color": "scrollbar.background",
"scrollbar-frame-color": "scrollbar.frame",
"scrollbar-scroller-color": "scrollbar.scroller",
"scrollbar-width": "10",
"size": "190, 565",
"transparent": "false",
"vertical-scrollbar": "true",
"wants-focus": "false"
},
"children": {
"CStringListControl": {
"attributes": {
"autosize": "left right top ",
"back-color": "~ TransparentCColor",
"back-color-selected": "list.background.selected",
"class": "CStringListControl",
"control-tag": "ModulePathList",
"default-value": "0.5",
"font": "list",
"font-color": "list.text",
"font-color-selected": "list.text.selected",
"hover-color": "None",
"line-color": "~ BlackCColor",
"line-width": "-1",
"max-value": "77",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "0, 0",
"row-height": "24",
"size": "182, 1872",
"style-hover": "false",
"text-alignment": "left",
"text-inset": "5",
"transparent": "false",
"wants-focus": "true",
"wheel-inc-value": "0.1"
}
}
}
},
"CTextLabel": {
"attributes": {
"back-color": "group.frame",
"background-offset": "0, 0",
"class": "CTextLabel",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "-1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "10, 5",
"round-rect-radius": "3",
"shadow-color": "~ RedCColor",
"size": "190, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "true",
"style-shadow-text": "false",
"text-alignment": "center",
"text-inset": "0, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "Modules",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"autosize": "left right top ",
"back-color": "group.frame",
"background-offset": "0, 0",
"class": "CTextLabel",
"control-tag": "Module::Path",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "-1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "210, 5",
"round-rect-radius": "3",
"shadow-color": "~ RedCColor",
"size": "535, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "true",
"style-shadow-text": "false",
"text-alignment": "center",
"text-inset": "0, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "/Users/AScheffler/Library/Audio/Plug-Ins/VST3/adelay.vst3",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CLayeredViewContainer": {
"attributes": {
"autosize": "left right top ",
"background-color": "~ TransparentCColor",
"background-color-draw-style": "filled and stroked",
"class": "CLayeredViewContainer",
"mouse-enabled": "true",
"opacity": "1",
"origin": "210, 30",
"size": "535, 140",
"transparent": "false",
"wants-focus": "false",
"z-index": "0"
},
"children": {
"CParamDisplay": {
"attributes": {
"autosize": "left right top bottom ",
"back-color": "group.background",
"background-offset": "0, 0",
"class": "CParamDisplay",
"default-value": "0.5",
"font": "~ NormalFont",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "group.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "0, 0",
"round-rect-radius": "6",
"shadow-color": "~ TransparentCColor",
"size": "535, 140",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "true",
"style-round-rect": "true",
"style-shadow-text": "false",
"text-alignment": "center",
"text-inset": "0, 0",
"text-rotation": "3.6",
"text-shadow-offset": "1, 1",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "10, 35",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "60, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "Vendor:",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "10, 60",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "60, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "URL:",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "10, 85",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "60, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "E-Mail:",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"autosize": "left right top ",
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"control-tag": "Factory::Vendor",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "75, 35",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "450, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "Steinberg Media Technologies",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"autosize": "left right top ",
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"control-tag": "Factory::URL",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "75, 60",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "450, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "http://www.steinberg.net",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"autosize": "left right top ",
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"control-tag": "Factory::EMail",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "75, 85",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "450, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "mailto:info@steinberg.de",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "10, 10",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "150, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "0, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "Factory Info:",
"transparent": "true",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "10, 110",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "60, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "Flags:",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"autosize": "left right top ",
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"control-tag": "Factory::Flags",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "75, 110",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "450, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "0b00000000000000000000000000010000",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
}
}
},
"CLayeredViewContainer": {
"attributes": {
"autosize": "left right top bottom ",
"background-color": "~ TransparentCColor",
"background-color-draw-style": "filled and stroked",
"class": "CLayeredViewContainer",
"mouse-enabled": "true",
"opacity": "1",
"origin": "210, 180",
"size": "535, 415",
"transparent": "false",
"wants-focus": "false",
"z-index": "0"
},
"children": {
"CParamDisplay": {
"attributes": {
"autosize": "left right top bottom ",
"back-color": "group.background",
"background-offset": "0, 0",
"class": "CParamDisplay",
"default-value": "0.5",
"font": "~ NormalFont",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "group.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "0, 0",
"round-rect-radius": "6",
"shadow-color": "~ TransparentCColor",
"size": "535, 415",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "true",
"style-round-rect": "true",
"style-shadow-text": "false",
"text-alignment": "center",
"text-inset": "0, 0",
"text-rotation": "3.6",
"text-shadow-offset": "1, 1",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "10, 10",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "150, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "0, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "Class Infos:",
"transparent": "true",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CScrollView": {
"attributes": {
"auto-drag-scrolling": "false",
"auto-hide-scrollbars": "true",
"autosize": "left top bottom ",
"background-color": "list.background",
"background-color-draw-style": "filled and stroked",
"bordered": "false",
"class": "CScrollView",
"container-size": "160, 72",
"follow-focus-view": "false",
"horizontal-scrollbar": "false",
"mouse-enabled": "true",
"opacity": "1",
"origin": "10, 35",
"overlay-scrollbars": "false",
"scrollbar-background-color": "scrollbar.background",
"scrollbar-frame-color": "scrollbar.frame",
"scrollbar-scroller-color": "scrollbar.scroller",
"scrollbar-width": "10",
"size": "160, 370",
"transparent": "false",
"vertical-scrollbar": "true",
"wants-focus": "false"
},
"children": {
"CStringListControl": {
"attributes": {
"autosize": "left right top ",
"back-color": "~ TransparentCColor",
"back-color-selected": "list.background.selected",
"class": "CStringListControl",
"control-tag": "ClassInfoList",
"default-value": "0.5",
"font": "list",
"font-color": "list.text",
"font-color-selected": "list.text.selected",
"hover-color": "None",
"line-color": "~ BlackCColor",
"line-width": "-1",
"max-value": "2",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "0, 0",
"row-height": "24",
"size": "160, 72",
"style-hover": "false",
"text-alignment": "left",
"text-inset": "5",
"transparent": "false",
"wants-focus": "true",
"wheel-inc-value": "0.1"
}
}
}
},
"CTextLabel": {
"attributes": {
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "175, 60",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "95, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "Name:",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"autosize": "left right top ",
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"control-tag": "ClassInfo::Name",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "275, 60",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "245, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "ADelay",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "175, 85",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "95, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "Vendor:",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"autosize": "left right top ",
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"control-tag": "ClassInfo::Vendor",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "275, 85",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "245, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "Steinberg Media Technologies",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "175, 110",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "95, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "Version:",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"autosize": "left right top ",
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"control-tag": "ClassInfo::Version",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "275, 110",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "245, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "1.1.0.1",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "175, 135",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "95, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "SDKVersion:",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"autosize": "left right top ",
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"control-tag": "ClassInfo::SDKVersion",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "275, 135",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "245, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "VST 3.7.1",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "175, 160",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "95, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "SubCategories:",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"autosize": "left right top ",
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"control-tag": "ClassInfo::SubCategories",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "275, 160",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "245, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "Fx|Delay",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "175, 35",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "95, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "Category:",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"autosize": "left right top ",
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"control-tag": "ClassInfo::Category",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "275, 35",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "245, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "Audio Module Class",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "175, 185",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "95, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "UID:",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"autosize": "left right top ",
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"control-tag": "ClassInfo::ClassID",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "275, 185",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "245, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "0CDBB66985D548A9BFD8371909D24BB3",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "175, 210",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "95, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "Cardinality:",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"autosize": "left right top ",
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"control-tag": "ClassInfo::Cardinality",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "275, 210",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "245, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "175, 235",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "95, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "Class Flags:",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CTextLabel": {
"attributes": {
"autosize": "left right top ",
"back-color": "list.background",
"background-offset": "0, 0",
"class": "CTextLabel",
"control-tag": "ClassInfo::ClassFlags",
"default-value": "0.5",
"font": "list",
"font-antialias": "true",
"font-color": "list.text",
"frame-color": "list.frame",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "275, 235",
"round-rect-radius": "6",
"shadow-color": "~ RedCColor",
"size": "245, 20",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "left",
"text-inset": "5, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"title": "0b00000000000000000000000000000001",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"CScrollView": {
"attributes": {
"auto-drag-scrolling": "false",
"auto-hide-scrollbars": "true",
"autosize": "left right top bottom ",
"background-color": "list.background",
"background-color-draw-style": "filled and stroked",
"bordered": "false",
"class": "CScrollView",
"container-size": "50, 50",
"follow-focus-view": "false",
"horizontal-scrollbar": "true",
"mouse-enabled": "true",
"opacity": "1",
"origin": "175, 260",
"overlay-scrollbars": "false",
"scrollbar-background-color": "scrollbar.background",
"scrollbar-frame-color": "scrollbar.frame",
"scrollbar-scroller-color": "scrollbar.scroller",
"scrollbar-width": "10",
"size": "345, 145",
"sub-controller": "SnapshotViewController",
"transparent": "false",
"vertical-scrollbar": "true",
"wants-focus": "false"
},
"children": {
"CView": {
"attributes": {
"class": "CView",
"custom-view-name": "ImageView",
"mouse-enabled": "true",
"opacity": "1",
"origin": "0, 0",
"size": "50, 50",
"transparent": "false",
"wants-focus": "false"
}
}
}
}
}
}
}
}
}
}
} vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/inspectorapp/source/ 0000775 0000000 0000000 00000000000 14615113443 0024310 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/inspectorapp/source/app.cpp 0000664 0000000 0000000 00000006263 14615113443 0025603 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format SMTGSequencer
// Project : VST SDK
//
// Category : VST3Inspector
// Filename : public.sdk/samples/vst-hosting/inspectorapp/app.cpp
// Created by : Steinberg, 01/2021
// Description : VST3 Inspector Application
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#include "vstgui/standalone/include/helpers/appdelegate.h"
#include "vstgui/standalone/include/helpers/windowlistener.h"
#include "vstgui/standalone/include/iapplication.h"
#include "window.h"
//------------------------------------------------------------------------
namespace VST3Inspector {
using namespace VSTGUI;
using namespace VSTGUI::Standalone;
//------------------------------------------------------------------------
struct App : Application::DelegateAdapter, WindowListenerAdapter
{
App () : Application::DelegateAdapter ({"VST3Inspector", "1.0.0", VSTGUI_STANDALONE_APP_URI}) {}
void finishLaunching () override
{
if (auto window = makeWindow ())
{
window->registerWindowListener (this);
window->show ();
}
}
void onClosed (const IWindow& window) override { IApplication::instance ().quit (); }
};
//------------------------------------------------------------------------
static Application::Init gAppDelegate (std::make_unique ());
//------------------------------------------------------------------------
} // VST3Inspector
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/inspectorapp/source/window.cpp 0000664 0000000 0000000 00000042756 14615113443 0026341 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format SMTGSequencer
// Project : VST SDK
//
// Category : VST3Inspector
// Filename : public.sdk/samples/vst-hosting/inspectorapp/window.cpp
// Created by : Steinberg, 01/2021
// Description : VST3 Inspector Application
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#include "window.h"
#include "vstgui/lib/cbitmap.h"
#include "vstgui/lib/platform/platformfactory.h"
#include "vstgui/standalone/include/helpers/menubuilder.h"
#include "vstgui/standalone/include/helpers/uidesc/customization.h"
#include "vstgui/standalone/include/helpers/value.h"
#include "vstgui/standalone/include/helpers/valuelistener.h"
#include "vstgui/standalone/include/helpers/windowcontroller.h"
#include "vstgui/standalone/include/ialertbox.h"
#include "vstgui/standalone/include/iapplication.h"
#include "vstgui/standalone/include/iasync.h"
#include "vstgui/standalone/include/iuidescwindow.h"
#include "vstgui/uidescription/cstream.h"
#include "vstgui/uidescription/delegationcontroller.h"
#include "vstgui/uidescription/iuidescription.h"
#include "vstgui/uidescription/uiattributes.h"
#include "public.sdk/source/vst/hosting/module.h"
#include "public.sdk/source/vst/moduleinfo/moduleinfo.h"
#include "public.sdk/source/vst/moduleinfo/moduleinfocreator.h"
#include "public.sdk/source/vst/moduleinfo/moduleinfoparser.h"
#include
#include
#include
//------------------------------------------------------------------------
namespace VST3Inspector {
namespace {
//------------------------------------------------------------------------
std::string loadFile (const std::string& path)
{
std::ifstream file (path, std::ios_base::in | std::ios_base::binary);
if (!file.is_open ())
return {};
auto size = file.seekg (0, std::ios_base::end).tellg ();
file.seekg (0, std::ios_base::beg);
std::string data;
data.resize (size);
file.read (data.data (), data.size ());
if (file.bad ())
return {};
return data;
}
//------------------------------------------------------------------------
} // anonymous
using namespace VSTGUI;
using namespace VSTGUI::Standalone;
using namespace Steinberg;
//------------------------------------------------------------------------
class DummyFactory : public IPluginFactory
{
public:
static DummyFactory* instance ()
{
static DummyFactory gInstance;
return &gInstance;
}
private:
tresult PLUGIN_API getFactoryInfo (PFactoryInfo* info) override
{
*info = {};
return kResultTrue;
}
int32 PLUGIN_API countClasses () override { return 0; }
tresult PLUGIN_API getClassInfo (int32 index, PClassInfo* info) override
{
return kResultFalse;
}
tresult PLUGIN_API createInstance (FIDString cid, FIDString _iid, void** obj) override
{
return kNoInterface;
}
tresult PLUGIN_API queryInterface (const TUID _iid, void** obj) override
{
QUERY_INTERFACE (_iid, obj, IPluginFactory::iid, IPluginFactory)
QUERY_INTERFACE (_iid, obj, FUnknown::iid, FUnknown)
return kNoInterface;
}
uint32 PLUGIN_API addRef () override { return 1000; }
uint32 PLUGIN_API release () override { return 1000; }
};
//------------------------------------------------------------------------
class InvalidModule : public VST3::Hosting::Module
{
public:
InvalidModule () { factory = VST3::Hosting::PluginFactory (DummyFactory::instance ()); }
private:
bool load (const std::string& path, std::string& errorDescription) override { return true; };
};
//------------------------------------------------------------------------
struct ValueMap
{
ValuePtr addValue (const ValuePtr& value)
{
auto index = valueList.size ();
valueList.push_back (value);
valueMap.insert ({value->getID ().getString (), index});
return value;
}
ValuePtr get (const std::string& ID)
{
auto it = valueMap.find (ID);
if (it != valueMap.end ())
return valueList.at (it->second);
return nullptr;
}
template
auto get (const std::string& ID)
{
if (auto value = get (ID))
{
return std::dynamic_pointer_cast (value);
}
return std::shared_ptr (nullptr);
}
const UIDesc::IModelBinding::ValueList& getValues () const { return valueList; }
private:
UIDesc::IModelBinding::ValueList valueList;
std::unordered_map valueMap;
};
//------------------------------------------------------------------------
static constexpr auto ModulePathListID = "ModulePathList";
static constexpr auto ModulePathID = "Module::Path";
static constexpr auto FactoryVendorID = "Factory::Vendor";
static constexpr auto FactoryUrlID = "Factory::URL";
static constexpr auto FactoryEMailID = "Factory::EMail";
static constexpr auto FactoryFlagsID = "Factory::Flags";
static constexpr auto ClassInfoListID = "ClassInfoList";
static constexpr auto ClassInfoClassID = "ClassInfo::ClassID";
static constexpr auto ClassInfoCategoryID = "ClassInfo::Category";
static constexpr auto ClassInfoNameID = "ClassInfo::Name";
static constexpr auto ClassInfoVendorID = "ClassInfo::Vendor";
static constexpr auto ClassInfoVersionID = "ClassInfo::Version";
static constexpr auto ClassInfoSDKVersionID = "ClassInfo::SDKVersion";
static constexpr auto ClassInfoSubCategoriesID = "ClassInfo::SubCategories";
static constexpr auto ClassInfoCardinalityID = "ClassInfo::Cardinality";
static constexpr auto ClassInfoClassFlagsID = "ClassInfo::ClassFlags";
using namespace VST3::Hosting;
//------------------------------------------------------------------------
struct SnapshotController : DelegationController, NonAtomicReferenceCounted
{
SnapshotController (IController* parent) : DelegationController (parent) {}
~SnapshotController () noexcept {}
CView* createView (const UIAttributes& attributes, const IUIDescription* description) override
{
if (auto viewName = attributes.getAttributeValue (IUIDescription::kCustomViewName))
{
if (*viewName == "ImageView")
{
imageView = VSTGUI::shared (new CView (CRect ()));
return imageView;
}
}
return controller->createView (attributes, description);
}
void setSnapshot (const std::string& moduleBasePath,
const ModuleInfo::SnapshotList* newSnapshot)
{
snapshot = newSnapshot ? *newSnapshot : ModuleInfo::SnapshotList ();
if (snapshot.empty ())
{
imageView->setBackground (nullptr);
imageView->setViewSize ({});
}
else
{
SharedPointer bitmap;
const auto& factory = getPlatformFactory ();
for (const auto& imageDesc : snapshot)
{
if (auto pb = factory.createBitmapFromPath (
(moduleBasePath + "/" + imageDesc.path).data ()))
{
pb->setScaleFactor (imageDesc.scaleFactor);
if (bitmap)
bitmap->addBitmap (pb);
else
bitmap = makeOwned (pb);
}
}
imageView->setBackground (bitmap);
if (bitmap)
{
auto viewSize = imageView->getViewSize ();
viewSize.setSize (bitmap->getSize ());
imageView->setViewSize (viewSize);
}
}
}
SharedPointer imageView;
ModuleInfo::SnapshotList snapshot;
};
//------------------------------------------------------------------------
struct WindowController : WindowControllerAdapter,
UIDesc::CustomizationAdapter,
UIDesc::IModelBinding,
MenuBuilderAdapter,
ValueListenerAdapter
{
WindowController ()
{
values.addValue (Value::makeStringListValue (ModulePathListID, {"", ""}))
->registerListener (this);
// Module Values
values.addValue (Value::makeStringValue (ModulePathID, ""));
// Factory Values
values.addValue (Value::makeStringValue (FactoryVendorID, ""));
values.addValue (Value::makeStringValue (FactoryUrlID, ""));
values.addValue (Value::makeStringValue (FactoryEMailID, ""));
values.addValue (Value::makeStringValue (FactoryFlagsID, ""));
values.addValue (Value::makeStringListValue (ClassInfoListID, {"", ""}))
->registerListener (this);
// Class Info Values
values.addValue (Value::makeStringValue (ClassInfoClassID, ""));
values.addValue (Value::makeStringValue (ClassInfoCategoryID, ""));
values.addValue (Value::makeStringValue (ClassInfoNameID, ""));
values.addValue (Value::makeStringValue (ClassInfoVendorID, ""));
values.addValue (Value::makeStringValue (ClassInfoVersionID, ""));
values.addValue (Value::makeStringValue (ClassInfoSDKVersionID, ""));
values.addValue (Value::makeStringValue (ClassInfoSubCategoriesID, ""));
values.addValue (Value::makeStringValue (ClassInfoCardinalityID, ""));
values.addValue (Value::makeStringValue (ClassInfoClassFlagsID, ""));
Async::schedule (Async::backgroundQueue (), [this] () {
auto modulePaths = Module::getModulePaths ();
Async::schedule (Async::mainQueue (),
[this, paths = std::move (modulePaths)] () mutable {
setModulePaths (std::move (paths));
});
});
}
static Optional lastPathComponent (const std::string& path)
{
#if SMTG_WINDOWS
static constexpr auto pathSeparator = '\\';
#else
static constexpr auto pathSeparator = '/';
#endif
size_t sepPos = path.find_last_of (pathSeparator);
if (sepPos == std::string::npos)
return {};
return {path.substr (sepPos + 1)};
}
void setModulePaths (Module::PathList&& pathList)
{
modulePathList = std::move (pathList);
std::sort (modulePathList.begin (), modulePathList.end (),
[] (const auto& lhs, const auto& rhs) {
auto lhsName = lastPathComponent (lhs);
auto rhsName = lastPathComponent (rhs);
if (lhsName && rhsName)
{
std::for_each (lhsName->begin (), lhsName->end (),
[] (auto& c) { c = std::tolower (c); });
std::for_each (rhsName->begin (), rhsName->end (),
[] (auto& c) { c = std::tolower (c); });
return *lhsName < *rhsName;
}
return lhs < rhs;
});
moduleInfos.clear ();
moduleInfos.resize (modulePathList.size ());
IStringListValue::StringList nameList;
for (const auto& path : modulePathList)
{
if (auto name = lastPathComponent (path))
nameList.emplace_back (UTF8String (*name));
else
nameList.emplace_back (UTF8String (path));
}
if (auto value = values.get (ModulePathListID))
value->updateStringList (nameList);
if (auto value = values.get (ModulePathListID))
Value::performSingleEdit (*value, 0.);
}
void onEndEdit (IValue& value) override
{
if (value.getID () == ModulePathListID)
{
onModuleSelection (value.getConverter ().normalizedToPlain (value.getValue ()));
}
if (value.getID () == ClassInfoListID)
{
onClassInfoSelection (value.getConverter ().normalizedToPlain (value.getValue ()));
}
}
void setStringValue (const std::string& valueID, const std::string& string)
{
auto value = values.get (valueID);
if (value)
Value::performStringValueEdit (*value, UTF8String (string));
}
std::string createFlagsString (int32_t flags) const
{
std::string flagsString = "0b";
for (int32_t i = 31; i >= 0; --i)
{
if (flags & (1 << i))
flagsString += "1";
else
flagsString += "0";
}
return flagsString;
}
std::string createSubCategoryString (const ModuleInfo::ClassInfo& info) const
{
std::string result;
for (const auto& cat : info.subCategories)
{
if (result.empty () == false)
result += "|";
result += cat;
}
return result;
}
void onClassInfoSelection (uint32_t index)
{
if (index >= moduleInfos[currentSelectedModule].classes.size ())
{
setStringValue (ClassInfoClassID, "");
setStringValue (ClassInfoCategoryID, "");
setStringValue (ClassInfoNameID, "");
setStringValue (ClassInfoVendorID, "");
setStringValue (ClassInfoVersionID, "");
setStringValue (ClassInfoSDKVersionID, "");
setStringValue (ClassInfoSubCategoriesID, "");
setStringValue (ClassInfoCardinalityID, "");
setStringValue (ClassInfoClassFlagsID, "");
if (snapShotController)
snapShotController->setSnapshot ("", nullptr);
return;
}
const auto& cl = moduleInfos[currentSelectedModule].classes[index];
setStringValue (ClassInfoClassID, cl.cid);
setStringValue (ClassInfoCategoryID, cl.category);
setStringValue (ClassInfoNameID, cl.name);
setStringValue (ClassInfoVendorID, cl.vendor);
setStringValue (ClassInfoVersionID, cl.version);
setStringValue (ClassInfoSDKVersionID, cl.sdkVersion);
setStringValue (ClassInfoSubCategoriesID, createSubCategoryString (cl));
if (cl.cardinality == Steinberg::PClassInfo::ClassCardinality::kManyInstances)
setStringValue (ClassInfoCardinalityID, "");
else
setStringValue (ClassInfoCardinalityID, std::to_string (cl.cardinality));
setStringValue (ClassInfoClassFlagsID, createFlagsString (cl.flags));
if (snapShotController)
snapShotController->setSnapshot (modulePathList[currentSelectedModule], &cl.snapshots);
}
void updateModuleInfo (uint32_t index)
{
const auto& modulePath = modulePathList[index];
if (auto moduleInfoPath = Module::getModuleInfoPath (modulePath))
{
auto moduleJson = loadFile (*moduleInfoPath);
if (auto moduleInfo = ModuleInfoLib::parseJson (moduleJson, nullptr))
{
moduleInfos[index] = *moduleInfo;
}
}
else
{
std::string errorDesc;
if (auto module = Module::create (modulePath, errorDesc))
{
moduleInfos[index] = ModuleInfoLib::createModuleInfo (*module.get (), true);
}
}
}
void onModuleSelection (uint32_t index)
{
if (index >= modulePathList.size ())
return;
currentSelectedModule = index;
if (moduleInfos[index].name.empty ())
{
updateModuleInfo (index);
}
const auto& moduleInfo = moduleInfos[index];
const auto& modulePath = modulePathList[index];
setStringValue (ModulePathID, modulePath);
setStringValue (FactoryVendorID, moduleInfo.factoryInfo.vendor);
setStringValue (FactoryUrlID, moduleInfo.factoryInfo.url);
setStringValue (FactoryEMailID, moduleInfo.factoryInfo.email);
setStringValue (FactoryFlagsID, createFlagsString (moduleInfo.factoryInfo.flags));
IStringListValue::StringList classInfoList;
for (const auto& classInfo : moduleInfo.classes)
{
classInfoList.emplace_back (classInfo.name);
}
if (auto value = values.get (ClassInfoListID))
{
value->updateStringList (classInfoList);
}
// select first class info
if (auto value = values.get (ClassInfoListID))
Value::performSingleEdit (*value, 0.);
}
const ValueList& getValues () const override { return values.getValues (); }
IController* createController (const UTF8StringView& name, IController* parent,
const IUIDescription* uiDesc) override
{
if (name == "SnapshotViewController")
{
snapShotController = VSTGUI::shared (new SnapshotController (parent));
return snapShotController;
}
return nullptr;
}
bool showCommandInMenu (const Interface& context, const Command& cmd) const override
{
return false;
}
private:
ValueMap values;
ValuePtr modulePathListValue;
SharedPointer snapShotController;
using ModuleInfoList = std::vector;
Module::PathList modulePathList;
ModuleInfoList moduleInfos;
uint32_t currentSelectedModule {0};
};
//------------------------------------------------------------------------
WindowPtr makeWindow ()
{
auto controller = std::make_shared ();
UIDesc::Config config;
config.uiDescFileName = "window.uidesc";
config.viewName = "MainWindow";
config.windowConfig.autoSaveFrameName = "MainWindow";
config.windowConfig.type = WindowType::Document;
config.windowConfig.style = WindowStyle ().border ().close ().centered ().size ();
config.windowConfig.title = "VST3 Inspector";
config.customization = controller;
config.modelBinding = controller;
return UIDesc::makeWindow (config);
}
//------------------------------------------------------------------------
} // VST3Inspector
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/inspectorapp/source/window.h 0000664 0000000 0000000 00000004762 14615113443 0026001 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format SMTGSequencer
// Project : VST SDK
//
// Category : VST3Inspector
// Filename : public.sdk/samples/vst-hosting/inspectorapp/window.h
// Created by : Steinberg, 01/2021
// Description : VST3 Inspector Application
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#include "vstgui/standalone/include/iwindow.h"
//------------------------------------------------------------------------
namespace VST3Inspector {
//------------------------------------------------------------------------
VSTGUI::Standalone::WindowPtr makeWindow ();
//------------------------------------------------------------------------
} // VST3Inspector
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/validator/ 0000775 0000000 0000000 00000000000 14615113443 0022266 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/validator/CMakeLists.txt 0000664 0000000 0000000 00000020157 14615113443 0025033 0 ustar 00root root 0000000 0000000
set(validator_sources
${SDK_ROOT}/public.sdk/source/common/memorystream.cpp
${SDK_ROOT}/public.sdk/source/main/moduleinit.cpp
${SDK_ROOT}/public.sdk/source/main/moduleinit.h
${SDK_ROOT}/public.sdk/source/vst/moduleinfo/moduleinfoparser.cpp
${SDK_ROOT}/public.sdk/source/vst/moduleinfo/moduleinfoparser.h
${SDK_ROOT}/public.sdk/source/vst/hosting/test/connectionproxytest.cpp
${SDK_ROOT}/public.sdk/source/vst/hosting/test/eventlisttest.cpp
${SDK_ROOT}/public.sdk/source/vst/hosting/test/hostclassestest.cpp
${SDK_ROOT}/public.sdk/source/vst/hosting/test/parameterchangestest.cpp
${SDK_ROOT}/public.sdk/source/vst/hosting/test/pluginterfacesupporttest.cpp
${SDK_ROOT}/public.sdk/source/vst/hosting/test/processdatatest.cpp
${SDK_ROOT}/public.sdk/source/vst/hosting/plugprovider.cpp
${SDK_ROOT}/public.sdk/source/vst/hosting/plugprovider.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/busactivation.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/busactivation.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/busconsistency.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/busconsistency.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/businvalidindex.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/businvalidindex.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/checkaudiobusarrangement.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/checkaudiobusarrangement.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/scanbusses.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/scanbusses.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/sidechainarrangement.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/sidechainarrangement.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/editorclasses.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/editorclasses.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/midilearn.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/midilearn.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/midimapping.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/midimapping.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/plugcompat.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/plugcompat.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/scanparameters.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/scanparameters.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/suspendresume.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/suspendresume.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/terminit.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/terminit.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/noteexpression/keyswitch.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/noteexpression/keyswitch.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/noteexpression/noteexpression.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/noteexpression/noteexpression.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/automation.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/automation.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/process.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/process.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processcontextrequirements.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processcontextrequirements.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processformat.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processformat.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processinputoverwriting.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processinputoverwriting.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processtail.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processtail.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processthreaded.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processthreaded.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/silenceflags.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/silenceflags.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/silenceprocessing.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/silenceprocessing.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/speakerarrangement.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/speakerarrangement.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/variableblocksize.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/variableblocksize.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/state/bypasspersistence.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/state/bypasspersistence.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/state/invalidstatetransition.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/state/invalidstatetransition.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/state/repeatidenticalstatetransition.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/state/repeatidenticalstatetransition.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/state/validstatetransition.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/state/validstatetransition.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/testbase.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/testbase.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/unit/checkunitstructure.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/unit/checkunitstructure.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/unit/scanprograms.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/unit/scanprograms.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/unit/scanunits.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/unit/scanunits.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/vststructsizecheck.h
${SDK_ROOT}/public.sdk/source/vst/testsuite/vsttestsuite.cpp
${SDK_ROOT}/public.sdk/source/vst/testsuite/vsttestsuite.h
${SDK_ROOT}/public.sdk/source/vst/utility/testing.cpp
${SDK_ROOT}/public.sdk/source/vst/utility/testing.h
source/main.cpp
source/usediids.cpp
source/validator.cpp
source/validator.h
source/testsuite.h
)
if(SMTG_MAC)
set(validator_sources
${validator_sources}
${SDK_ROOT}/public.sdk/source/vst/hosting/module_mac.mm
)
set_source_files_properties(
"${SDK_ROOT}/public.sdk/source/vst/hosting/module_mac.mm" PROPERTIES
COMPILE_FLAGS "-fobjc-arc"
)
elseif(SMTG_LINUX)
set(validator_sources
${validator_sources}
${SDK_ROOT}/public.sdk/source/vst/hosting/module_linux.cpp
)
elseif(SMTG_WIN)
set(validator_sources
${validator_sources}
${SDK_ROOT}/public.sdk/source/vst/hosting/module_win32.cpp
)
endif(SMTG_MAC)
set(target validator)
add_executable(${target} ${validator_sources})
if(SDK_IDE_HOSTING_EXAMPLES_FOLDER)
set_target_properties(${target}
PROPERTIES
${SDK_IDE_HOSTING_EXAMPLES_FOLDER}
)
endif(SDK_IDE_HOSTING_EXAMPLES_FOLDER)
target_compile_features(${target}
PUBLIC
cxx_std_17
)
target_link_libraries(${target}
PRIVATE
sdk_hosting
)
smtg_target_codesign(${target})
smtg_target_setup_universal_binary(${target})
if(APPLE AND NOT XCODE)
find_library(COCOA_FRAMEWORK Cocoa)
target_link_libraries(${target}
PRIVATE
${COCOA_FRAMEWORK}
)
endif(APPLE AND NOT XCODE)
#####################################################
if(SMTG_RUN_VST_VALIDATOR)
####################
# Workaround for Xcode 15 not allowing to add adhoc_codesign linker setting
####################
if(SMTG_MAC AND XCODE_VERSION VERSION_GREATER_EQUAL 15)
add_custom_command(
TARGET ${target} POST_BUILD
COMMENT "[SMTG] Adhoc codesign workaround for Xcode 15"
COMMAND codesign --force --verbose --sign -
"$"
)
endif()
add_custom_command(TARGET ${target} POST_BUILD
COMMAND $ "-selftest"
)
endif(SMTG_RUN_VST_VALIDATOR)
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/validator/source/ 0000775 0000000 0000000 00000000000 14615113443 0023566 5 ustar 00root root 0000000 0000000 vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/validator/source/main.cpp 0000664 0000000 0000000 00000007327 14615113443 0025227 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Project : VST SDK
//
// Category : Validator
// Filename : main.cpp
// Created by : Steinberg, 04/2005
// Description : main entry point
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#include "validator.h"
#include "public.sdk/source/vst/utility/stringconvert.h"
void* moduleHandle = nullptr;
extern bool InitModule ();
extern bool DeinitModule ();
//------------------------------------------------------------------------
int run (int argc, char* argv[])
{
InitModule ();
auto result = Steinberg::Vst::Validator (argc, argv).run ();
DeinitModule ();
return result;
}
//------------------------------------------------------------------------
#if SMTG_OS_WINDOWS
//------------------------------------------------------------------------
using Utf8String = std::string;
//------------------------------------------------------------------------
using Utf8Args = std::vector;
Utf8Args toUtf8Args (int argc, wchar_t* wargv[])
{
Utf8Args utf8Args;
for (int i = 0; i < argc; i++)
{
auto str = reinterpret_cast (wargv[i]);
utf8Args.push_back (VST3::StringConvert::convert (str));
}
return utf8Args;
}
//------------------------------------------------------------------------
using Utf8ArgPtrs = std::vector;
Utf8ArgPtrs toUtf8ArgPtrs (Utf8Args& utf8Args)
{
Utf8ArgPtrs utf8ArgPtrs;
for (auto& el : utf8Args)
{
utf8ArgPtrs.push_back (el.data ());
}
return utf8ArgPtrs;
}
//------------------------------------------------------------------------
int wmain (int argc, wchar_t* wargv[])
{
Utf8Args utf8Args = toUtf8Args (argc, wargv);
Utf8ArgPtrs utf8ArgPtrs = toUtf8ArgPtrs (utf8Args);
char** argv = &(utf8ArgPtrs.at (0));
return run (argc, argv);
}
#else
//------------------------------------------------------------------------
int main (int argc, char* argv[])
{
return run (argc, argv);
}
#endif // SMTG_OS_WINDOWS
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/validator/source/testsuite.h 0000664 0000000 0000000 00000010577 14615113443 0026002 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format SMTGSequencer
// Project : VST SDK
//
// Category : Validator
// Filename : testsuite.h
// Created by : Steinberg, 05/2019
// Description : VST 3 Plug-in Validator test suite class
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#pragma once
#include "base/source/fobject.h"
#include "pluginterfaces/test/itest.h"
#include
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
//------------------------------------------------------------------------
// TestSuite
//------------------------------------------------------------------------
class TestSuite : public ITestSuite, public FObject
{
public:
TestSuite (FIDString _name) : name (_name) {}
tresult PLUGIN_API addTest (FIDString _name, ITest* test) SMTG_OVERRIDE
{
tests.push_back (IPtr (NEW Test (_name, test), false));
return kResultTrue;
}
tresult PLUGIN_API addTestSuite (FIDString _name, ITestSuite* testSuite) SMTG_OVERRIDE
{
testSuites.push_back (std::make_pair (_name, testSuite));
return kResultTrue;
}
tresult PLUGIN_API setEnvironment (ITest* /*environment*/) SMTG_OVERRIDE
{
return kNotImplemented;
}
int32 getTestCount () const { return static_cast (tests.size ()); }
tresult getTest (int32 index, ITest*& _test, std::string& _name) const
{
if (auto test = tests.at (index))
{
_test = test->test;
_name = test->name;
return kResultTrue;
}
return kResultFalse;
}
tresult getTestSuite (int32 index, ITestSuite*& testSuite, std::string& _name) const
{
if (index < 0 || index >= int32 (testSuites.size ()))
return kInvalidArgument;
const auto& ts = testSuites[index];
_name = ts.first;
testSuite = ts.second;
return kResultTrue;
}
ITestSuite* getTestSuite (FIDString _name) const
{
for (const auto& testSuite : testSuites)
{
if (testSuite.first == _name)
return testSuite.second;
}
return nullptr;
}
const std::string& getName () const { return name; }
OBJ_METHODS (TestSuite, FObject)
REFCOUNT_METHODS (FObject)
DEF_INTERFACES_1 (ITestSuite, FObject)
protected:
class Test : public FObject
{
public:
Test (FIDString _name, ITest* _test) : name (_name), test (_test) {}
std::string name;
IPtr test;
};
std::string name;
std::vector> tests;
using TestSuitePair = std::pair>;
using TestSuiteVector = std::vector;
TestSuiteVector testSuites;
};
//------------------------------------------------------------------------
} // Vst
} // Steinberg
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/validator/source/usediids.cpp 0000664 0000000 0000000 00000005131 14615113443 0026103 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Project : VST SDK
//
// Category : Validator
// Filename : public.sdk/samples/vst-hosting/validator/source/usediids.cpp
// Created by : Steinberg 09.2008
// Description : Interface symbols file
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
//#define INIT_CLASS_IID
// This macro definition modifies the behavior of DECLARE_CLASS_IID (funknown.h)
// and produces the actual symbols for all interface identifiers.
// It must be defined before including the interface headers and
// in only one source file!
//------------------------------------------------------------------------
//#define INIT_CLASS_IID
#include "pluginterfaces/base/ipluginbase.h"
#include "pluginterfaces/test/itest.h"
namespace Steinberg {
DEF_CLASS_IID (ITestResult)
}
vst3sdk-3.7.10.14+~4.13.3/samples/vst-hosting/validator/source/validator.cpp 0000664 0000000 0000000 00000066176 14615113443 0026277 0 ustar 00root root 0000000 0000000 //-----------------------------------------------------------------------------
// Flags : clang-format SMTGSequencer
// Project : VST SDK
//
// Category : Validator
// Filename : validator.cpp
// Created by : Steinberg, 04/2005
// Description : VST 3 Plug-in Validator class
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Steinberg Media Technologies nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#include "validator.h"
#include "testsuite.h"
#include "public.sdk/source/vst/hosting/plugprovider.h"
#include "public.sdk/source/vst/testsuite/general/plugcompat.h"
#include "public.sdk/source/vst/testsuite/vststructsizecheck.h"
#include "public.sdk/source/vst/utility/stringconvert.h"
#include "public.sdk/source/vst/utility/testing.h"
#include "base/source/fcommandline.h"
#include "pluginterfaces/base/iplugincompatibility.h"
#include "pluginterfaces/vst/ivstaudioprocessor.h"
#include "pluginterfaces/vst/ivstcomponent.h"
#include "pluginterfaces/vst/ivsteditcontroller.h"
#include "pluginterfaces/vst/ivsthostapplication.h"
#include "pluginterfaces/vst/ivstunits.h"
#include "pluginterfaces/base/funknownimpl.h"
#include "pluginterfaces/gui/iplugview.h"
#if SMTG_OS_WINDOWS
#include
#include
#endif
#include
#include
#include
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace {
constexpr auto SEPARATOR = "-------------------------------------------------------------\n";
constexpr auto VALIDATOR_INFO = kVstVersionString
" Plug-in Validator\n"
"Program by Steinberg (Built on " __DATE__ ")\n";
//------------------------------------------------------------------------
bool filterClassCategory (FIDString category, FIDString classCategory)
{
return strcmp (category, classCategory) == 0;
}
//------------------------------------------------------------------------
void printAllInstalledPlugins (std::ostream* os)
{
if (!os)
return;
*os << "Searching installed Plug-ins...\n";
os->flush ();
auto paths = VST3::Hosting::Module::getModulePaths ();
if (paths.empty ())
{
*os << "No Plug-ins found.\n";
return;
}
for (const auto& path : paths)
{
*os << path << "\n";
}
}
//------------------------------------------------------------------------
void printAllSnapshots (std::ostream* os)
{
if (!os)
return;
*os << "Searching installed Plug-ins...\n";
auto paths = VST3::Hosting::Module::getModulePaths ();
if (paths.empty ())
{
*os << "No Plug-ins found.\n";
return;
}
for (const auto& path : paths)
{
auto snapshots = VST3::Hosting::Module::getSnapshots (path);
if (snapshots.empty ())
{
*os << "No snapshots in " << path << "\n";
continue;
}
for (auto& snapshot : snapshots)
{
for (auto& desc : snapshot.images)
{
*os << "Snapshot : " << desc.path << "[" << desc.scaleFactor << "x]\n";
}
}
}
}
//------------------------------------------------------------------------
void printFactoryInfo (const VST3::Hosting::PluginFactory& factory, std::ostream* os)
{
if (os)
{
*os << "* Scanning classes...\n\n";
auto factoryInfo = factory.info ();
*os << " Factory Info:\n\tvendor = " << factoryInfo.vendor ()
<< "\n\turl = " << factoryInfo.url () << "\n\temail = " << factoryInfo.email ()
<< "\n\n";
//---print all included plug-ins---------------
uint32 i = 0;
for (auto& classInfo : factory.classInfos ())
{
*os << " Class Info " << i << ":\n\tname = " << classInfo.name ()
<< "\n\tcategory = " << classInfo.category ()
<< "\n\tsubCategories = " << classInfo.subCategoriesString ()
<< "\n\tversion = " << classInfo.version ()
<< "\n\tsdkVersion = " << classInfo.sdkVersion ()
<< "\n\tcid = " << classInfo.ID ().toString () << "\n\n";
++i;
}
}
}
//------------------------------------------------------------------------
void checkModuleSnapshots (const VST3::Hosting::Module::Ptr& module, std::ostream* infoStream)
{
if (infoStream)
*infoStream << "* Checking snapshots...\n\n";
auto snapshots = VST3::Hosting::Module::getSnapshots (module->getPath ());
if (snapshots.empty ())
{
if (infoStream)
*infoStream << "Info: No snapshots in Bundle.\n\n";
}
else
{
for (auto& classInfo : module->getFactory ().classInfos ())
{
if (!filterClassCategory (kVstAudioEffectClass, classInfo.category ().data ()))
continue;
bool found = false;
for (auto& snapshot : snapshots)
{
if (snapshot.uid == classInfo.ID ())
{
found = true;
if (infoStream)
{
*infoStream << "Found snapshots for '" << classInfo.name () << "'\n";
for (auto& image : snapshot.images)
*infoStream << " - " << image.path << " [" << image.scaleFactor
<< "x]\n";
*infoStream << "\n";
}
break;
}
}
if (!found)
{
if (infoStream)
{
*infoStream << "Info: No snapshot for '" << classInfo.name ()
<< "' in Bundle.\n\n";
}
}
}
}
}
#if SMTG_OS_LINUX
//------------------------------------------------------------------------
struct DummyRunLoop : U::ImplementsNonDestroyable>
{
using IEventHandler = Steinberg::Linux::IEventHandler;
using ITimerHandler = Steinberg::Linux::ITimerHandler;
using FileDescriptor = Steinberg::Linux::FileDescriptor;
using TimerInterval = Steinberg::Linux::TimerInterval;
static Steinberg::Linux::IRunLoop& instance ()
{
static DummyRunLoop drl;
return drl;
}
tresult PLUGIN_API registerEventHandler (IEventHandler* handler, FileDescriptor fd) override
{
return kNotImplemented;
}
tresult PLUGIN_API unregisterEventHandler (IEventHandler* handler) override
{
return kNotImplemented;
}
tresult PLUGIN_API registerTimer (ITimerHandler* handler, TimerInterval milliseconds) override
{
return kNotImplemented;
}
tresult PLUGIN_API unregisterTimer (ITimerHandler* handler) override { return kNotImplemented; }
};
#endif
//------------------------------------------------------------------------
//-- Options
constexpr auto optHelp = "help";
constexpr auto optVersion = "version";
constexpr auto optLocalInstance = "l";
constexpr auto optSuiteName = "suite";
constexpr auto optExtensiveTests = "e";
constexpr auto optQuiet = "q";
constexpr auto optTestComponentPath = "test-component";
constexpr auto optListInstalledPlugIns = "list";
constexpr auto optListPlugInSnapshots = "snapshots";
constexpr auto optCID = "cid";
constexpr auto optSelftest = "selftest";
//------------------------------------------------------------------------
} // anonymous
//------------------------------------------------------------------------
// Validator
//------------------------------------------------------------------------
Validator::Validator (int argc, char* argv[]) : argc (argc), argv (argv)
{
infoStream = &std::cout;
errorStream = &std::cout;
errorStream->setf (std::ios::unitbuf);
mPlugInterfaceSupport = owned (NEW PlugInterfaceSupport);
PluginContextFactory::instance ().setPluginContext (this->unknownCast ());
TestingPluginContext::set (this->unknownCast ());
}
//------------------------------------------------------------------------
Validator::~Validator ()
{
}
//-----------------------------------------------------------------------------
tresult PLUGIN_API Validator::queryInterface (const char* _iid, void** obj)
{
QUERY_INTERFACE (_iid, obj, IHostApplication::iid, IHostApplication)
QUERY_INTERFACE (_iid, obj, ITestResult::iid, ITestResult)
if (mPlugInterfaceSupport && mPlugInterfaceSupport->queryInterface (_iid, obj) == kResultTrue)
return ::Steinberg::kResultOk;
return FObject::queryInterface (_iid, obj);
}
//------------------------------------------------------------------------
void PLUGIN_API Validator::addErrorMessage (const tchar* msg)
{
if (errorStream)
{
auto str = VST3::StringConvert::convert (msg);
if (addErrorWarningTextToOutput)
*errorStream << "ERROR: " << str << "\n";
else
*errorStream << str << "\n";
}
}
//------------------------------------------------------------------------
void PLUGIN_API Validator::addMessage (const tchar* msg)
{
if (infoStream)
{
auto str = VST3::StringConvert::convert (msg);
if (addErrorWarningTextToOutput)
*infoStream << "Info: " << str << "\n";
else
*infoStream << str << "\n";
}
}
//------------------------------------------------------------------------
tresult PLUGIN_API Validator::getName (String128 name)
{
VST3::StringConvert::convert ("vstvalidator", name, 127);
return kResultTrue;
}
//------------------------------------------------------------------------
tresult PLUGIN_API Validator::createInstance (TUID cid, TUID iid, void** obj)
{
FUID classID = FUID::fromTUID (cid);
FUID interfaceID = FUID::fromTUID (iid);
if (classID == IMessage::iid && interfaceID == IMessage::iid)
{
*obj = new HostMessage;
return kResultTrue;
}
else if (classID == IAttributeList::iid && interfaceID == IAttributeList::iid)
{
if (auto al = HostAttributeList::make ())
{
*obj = al.take ();
return kResultTrue;
}
return kOutOfMemory;
}
*obj = nullptr;
return kResultFalse;
}
//------------------------------------------------------------------------
int Validator::run ()
{
// defaults
bool useGlobalInstance = true;
bool useExtensiveTests = false;
std::string testSuiteName;
// parse command line
CommandLine::Descriptions desc;
CommandLine::VariablesMap valueMap;
CommandLine::FilesVector files;
using Description = CommandLine::Description;
desc.addOptions (
kVstVersionString " Plug-in Validator",
{{optHelp, "Print help", Description::kBool},
{optVersion, "Print version", Description::kBool},
{optLocalInstance, "Use local instance per test", Description::kBool},
{optSuiteName, "[name] Only run a special test suite", Description::kString},
{optExtensiveTests, "Run extensive tests [may take a long time]", Description::kBool},
{optQuiet, "Only print errors", Description::kBool},
{optCID, "Only test processor with specified class ID", Description::kString},
{optTestComponentPath,
"[path] Path to an additional component which includes custom tests",
Description::kString},
{optListInstalledPlugIns, "Show all installed Plug-Ins", Description::kBool},
{optSelftest, "Run a selftest", Description::kBool},
{optListPlugInSnapshots, "List snapshots from all installed Plug-Ins",
Description::kBool}});
CommandLine::parse (argc, argv, desc, valueMap, &files);
if (valueMap.count (optVersion))
{
std::cout << VALIDATOR_INFO;
return 0;
}
else if (valueMap.count (optListInstalledPlugIns))
{
printAllInstalledPlugins (infoStream);
return 0;
}
else if (valueMap.count (optListPlugInSnapshots))
{
printAllSnapshots (infoStream);
return 0;
}
else if (valueMap.count (optSelftest))
{
addErrorWarningTextToOutput = false;
auto testFactoryInstance = owned (createTestFactoryInstance (nullptr));
FUnknownPtr testFactory (testFactoryInstance);
if (testFactory)
{
std::cout << "Running validator selftest:\n\n";
IPtr testSuite = owned (new TestSuite (""));
if (testFactory->createTests (nullptr, testSuite) == kResultTrue)
runTestSuite (testSuite, nullptr);
std::cout << "Executed " << (numTestsFailed + numTestsPassed) << " Tests.\n";
std::cout << numTestsFailed << " failed test(s).\n";
return numTestsFailed == 0 ? 0 : 1;
}
return 1;
}
else if (valueMap.hasError () || valueMap.count (optHelp) || files.empty ())
{
std::cout << "\n" << desc << "\n";
std::cout << "Usage: vstvalidator [options] vst3module\n\n";
return 1;
}
if (valueMap.count (optLocalInstance))
useGlobalInstance = false;
if (valueMap.count (optExtensiveTests))
useExtensiveTests = true;
if (valueMap.count (optQuiet))
infoStream = nullptr;
if (valueMap.count (optSuiteName))
testSuiteName = valueMap[optSuiteName];
VST3::Optional testProcessor;
if (valueMap.count (optCID))
testProcessor = VST3::UID::fromString (valueMap[optCID]);
std::string customTestComponentPath;
if (valueMap.count (optTestComponentPath))
customTestComponentPath = valueMap[optTestComponentPath];
auto globalFailure = false;
for (auto& path : files)
{
#if SMTG_OS_WINDOWS
// TODO: Impl
#else
// if path is not absolute, create one
if (path[0] != '/')
{
auto realPath = realpath (path.data (), NULL);
if (realPath)
{
path.assign (realPath);
free (realPath);
}
}
if (customTestComponentPath.empty () == false && customTestComponentPath[0] != '/')
{
auto realPath = realpath (customTestComponentPath.data (), NULL);
if (realPath)
{
customTestComponentPath.assign (realPath);
free (realPath);
}
}
#endif
//---load VST module-----------------
if (infoStream)
*infoStream << "* Loading module...\n\n\t" << path << "\n\n";
std::string error;
auto module = Module::create (path, error);
if (!module)
{
*errorStream << "Invalid Module!\n";
if (!error.empty ())
*errorStream << error << "\n";
return -1;
}
#if SMTG_OS_LINUX
module->getFactory ().setHostContext (&DummyRunLoop::instance ());
#endif
testModule (module, {useGlobalInstance, useExtensiveTests, customTestComponentPath,
testSuiteName, std::move (testProcessor)});
if (numTestsFailed > 0)
globalFailure = true;
}
return globalFailure ? -1 : 0;
}
//------------------------------------------------------------------------
void Validator::testModule (Module::Ptr module, const ModuleTestConfig& config)
{
using TestFactoryMap = std::map>;
using PlugProviderVector = std::vector>;
numTestsFailed = numTestsPassed = 0;
auto factory = module->getFactory ();
printFactoryInfo (module->getFactory (), infoStream);
//---check for snapshots-----------------
checkModuleSnapshots (module, infoStream);
Module::Ptr testModule;
PlugProviderVector plugProviders;
TestFactoryMap testFactories;
IPtr plugCompatibility;
auto testSuite = owned (new TestSuite ("Tests"));
//---create tests---------------
if (infoStream)
*infoStream << "* Creating tests...\n\n";
for (auto& classInfo : factory.classInfos ())
{
if (filterClassCategory (kVstAudioEffectClass, classInfo.category ().data ()))
{
if (!config.testProcessor || *config.testProcessor == classInfo.ID ())
{
auto plugProvider =
owned (new PlugProvider (factory, classInfo, config.useGlobalInstance));
if (plugProvider)
{
auto tests = createTests (plugProvider, classInfo.name ().data (),
config.useExtensiveTests);
testSuite->addTestSuite (classInfo.name ().data (), tests);
plugProviders.emplace_back (plugProvider);
}
}
}
else if (filterClassCategory (kTestClass, classInfo.category ().data ()))
{ // gather test factories supplied by the plug-in
if (auto testFactory = factory.createInstance (classInfo.ID ()))
{
testFactories.insert (std::make_pair (classInfo.name ().data (), testFactory));
}
}
else if (filterClassCategory (kPluginCompatibilityClass, classInfo.category ().data ()))
{
if (plugCompatibility)
{
if (errorStream)
{
*errorStream
<< "Error: Factory contains multiple Plugin Compatibility classes.\n";
}
++numTestsFailed;
}
plugCompatibility = factory.createInstance (classInfo.ID ());
if (!plugCompatibility)
{
if (errorStream)
{
*errorStream << "Error: Failed creating IPluginCompatibility instance.\n";
}
}
}
}
// now check testModule if supplied
if (config.customTestComponentPath.empty () == false)
{
std::string error;
testModule = Module::create (config.customTestComponentPath, error);
if (testModule)
{
const auto& _factory = testModule->getFactory ();
for (const auto& classInfo : _factory.classInfos ())
{
if (filterClassCategory (kTestClass, classInfo.category ().data ()))
{ // gather test factories supplied by the plug-in
if (auto testFactory = _factory.createInstance (classInfo.ID ()))
{
testFactories.insert (
std::make_pair (classInfo.name ().data (), testFactory));
}
}
}
}
else if (errorStream)
{
*errorStream << "Could not create custom test component ["
<< config.customTestComponentPath << "]\n";
}
}
if (infoStream && !testFactories.empty ())
*infoStream << "* Creating Plug-in supplied tests...\n\n";
// create plug-in supplied tests
for (const auto& item : testFactories)
{
for (const auto& plugProvider : plugProviders)
{
IPtr plugTestSuite = owned (new TestSuite (item.first.data ()));
if (item.second->createTests (plugProvider->unknownCast (), plugTestSuite) ==
kResultTrue)
{
testSuite->addTestSuite (plugTestSuite->getName ().data (), plugTestSuite);
}
}
}
testFactories.clear ();
//---run tests---------------------------
if (infoStream)
*infoStream << "* Running tests...\n\n";
runTestSuite (testSuite,
config.testSuiteName.empty () ? nullptr : config.testSuiteName.data ());
if (plugCompatibility)
{
if (!checkPluginCompatibility (module, plugCompatibility, errorStream))
++numTestsFailed;
}
if (infoStream)
{
*infoStream << SEPARATOR;
*infoStream << "Result: " << numTestsPassed << " tests passed, " << numTestsFailed
<< " tests failed\n";
*infoStream << SEPARATOR;
}
}
//------------------------------------------------------------------------
namespace { // anonymous
//------------------------------------------------------------------------
template
void createTest (ITestSuite* parent, ITestPlugProvider* plugProvider, Args&&... arguments)
{
auto test = owned (new T (plugProvider, std::forward (arguments)...));
parent->addTest (test->getName (), test);
}
//------------------------------------------------------------------------
void createSpeakerArrangementTest (ITestSuite* parent, ITestPlugProvider* plugProvider,
SymbolicSampleSizes sampleSize, SpeakerArrangement inSpArr,
SpeakerArrangement outSpArr)
{
createTest (parent, plugProvider, sampleSize, inSpArr, outSpArr);
}
//------------------------------------------------------------------------
void createPrecisionTests (ITestSuite* parent, ITestPlugProvider* plugProvider,
SymbolicSampleSizes sampleSize, bool extensive)
{
createTest (parent, plugProvider, sampleSize);
createTest (parent, plugProvider, sampleSize);
createTest (parent, plugProvider, sampleSize);
createTest (parent, plugProvider, sampleSize);
createTest (parent, plugProvider, sampleSize);
createTest (parent, plugProvider, sampleSize);
createTest (parent, plugProvider, sampleSize);
createTest (parent, plugProvider, sampleSize);
createTest (parent, plugProvider, sampleSize);
createTest (parent, plugProvider, sampleSize);
if (extensive)
{
constexpr std::array saArray = {
{SpeakerArr::kMono, SpeakerArr::kStereo, SpeakerArr::kStereoSurround,
SpeakerArr::kStereoCenter, SpeakerArr::kStereoSide, SpeakerArr::kStereoCLfe,
SpeakerArr::k30Cine, SpeakerArr::k30Music, SpeakerArr::k31Cine, SpeakerArr::k31Music,
SpeakerArr::k40Cine, SpeakerArr::k40Music, SpeakerArr::k41Cine, SpeakerArr::k41Music,
SpeakerArr::k50}};
for (auto inArr : saArray)
{
for (auto outArr : saArray)
{
createSpeakerArrangementTest (parent, plugProvider, sampleSize, inArr, outArr);
}
}
constexpr std::array