diff --git a/.gitignore b/.gitignore
index ef505672..9dd498f6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,17 @@
-/Debug
-/Release
-/FlexASIO.vcxproj.user
+*.vcxproj.user
.vs/
-x64/
-redist/
-FlexASIO-*.exe
-ASIOSDK2.3.1/
+
+/ASIOSDK2.3.1/
+
+/redist/
+/FlexASIO-*.exe
+
+/Debug/
+/Release/
+/x64/
+/ASIOHost/Debug/
+/ASIOHost/Release/
+/ASIOHost/x64/
+/FlexASIOTest/Release/
+/FlexASIOTest/Debug/
+/FlexASIOTest/x64/
diff --git a/ASIOHost/ASIOHost.vcxproj b/ASIOHost/ASIOHost.vcxproj
new file mode 100644
index 00000000..2e025bbf
--- /dev/null
+++ b/ASIOHost/ASIOHost.vcxproj
@@ -0,0 +1,140 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 15.0
+ {10C0DB40-8F17-4EFD-ABC5-8DFDED9A6910}
+ ASIO
+ 10.0.17763.0
+
+
+
+ StaticLibrary
+ true
+ v141
+ MultiByte
+
+
+ StaticLibrary
+ false
+ v141
+ true
+ MultiByte
+
+
+ StaticLibrary
+ true
+ v141
+ MultiByte
+
+
+ StaticLibrary
+ false
+ v141
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Level3
+ Disabled
+ true
+ true
+ $(SolutionDir)ASIOSDK2.3.1\common;$(SolutionDir)ASIOSDK2.3.1\host;$(SolutionDir)ASIOSDK2.3.1\host\pc;%(AdditionalIncludeDirectories)
+ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+
+
+
+
+ Level3
+ Disabled
+ true
+ true
+ $(SolutionDir)ASIOSDK2.3.1\common;$(SolutionDir)ASIOSDK2.3.1\host;$(SolutionDir)ASIOSDK2.3.1\host\pc;%(AdditionalIncludeDirectories)
+ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ true
+ $(SolutionDir)ASIOSDK2.3.1\common;$(SolutionDir)ASIOSDK2.3.1\host;$(SolutionDir)ASIOSDK2.3.1\host\pc;%(AdditionalIncludeDirectories)
+ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+
+
+ true
+ true
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ true
+ $(SolutionDir)ASIOSDK2.3.1\common;$(SolutionDir)ASIOSDK2.3.1\host;$(SolutionDir)ASIOSDK2.3.1\host\pc;%(AdditionalIncludeDirectories)
+ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+
+
+ true
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FlexASIO.sln b/FlexASIO.sln
index 36f019f6..c38f0a75 100644
--- a/FlexASIO.sln
+++ b/FlexASIO.sln
@@ -5,6 +5,13 @@ VisualStudioVersion = 15.0.28010.2046
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FlexASIO", "FlexASIO.vcxproj", "{EFC61192-2DB9-46B1-BF85-98FC6EF1E6D1}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ASIOHost", "ASIOHost\ASIOHost.vcxproj", "{10C0DB40-8F17-4EFD-ABC5-8DFDED9A6910}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FlexASIOTest", "FlexASIOTest\FlexASIOTest.vcxproj", "{84D0CD72-2EE0-4C89-AE29-615C021779BE}"
+ ProjectSection(ProjectDependencies) = postProject
+ {10C0DB40-8F17-4EFD-ABC5-8DFDED9A6910} = {10C0DB40-8F17-4EFD-ABC5-8DFDED9A6910}
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -21,6 +28,22 @@ Global
{EFC61192-2DB9-46B1-BF85-98FC6EF1E6D1}.Release|Win32.Build.0 = Release|Win32
{EFC61192-2DB9-46B1-BF85-98FC6EF1E6D1}.Release|x64.ActiveCfg = Release|x64
{EFC61192-2DB9-46B1-BF85-98FC6EF1E6D1}.Release|x64.Build.0 = Release|x64
+ {10C0DB40-8F17-4EFD-ABC5-8DFDED9A6910}.Debug|Win32.ActiveCfg = Debug|Win32
+ {10C0DB40-8F17-4EFD-ABC5-8DFDED9A6910}.Debug|Win32.Build.0 = Debug|Win32
+ {10C0DB40-8F17-4EFD-ABC5-8DFDED9A6910}.Debug|x64.ActiveCfg = Debug|x64
+ {10C0DB40-8F17-4EFD-ABC5-8DFDED9A6910}.Debug|x64.Build.0 = Debug|x64
+ {10C0DB40-8F17-4EFD-ABC5-8DFDED9A6910}.Release|Win32.ActiveCfg = Release|Win32
+ {10C0DB40-8F17-4EFD-ABC5-8DFDED9A6910}.Release|Win32.Build.0 = Release|Win32
+ {10C0DB40-8F17-4EFD-ABC5-8DFDED9A6910}.Release|x64.ActiveCfg = Release|x64
+ {10C0DB40-8F17-4EFD-ABC5-8DFDED9A6910}.Release|x64.Build.0 = Release|x64
+ {84D0CD72-2EE0-4C89-AE29-615C021779BE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {84D0CD72-2EE0-4C89-AE29-615C021779BE}.Debug|Win32.Build.0 = Debug|Win32
+ {84D0CD72-2EE0-4C89-AE29-615C021779BE}.Debug|x64.ActiveCfg = Debug|x64
+ {84D0CD72-2EE0-4C89-AE29-615C021779BE}.Debug|x64.Build.0 = Debug|x64
+ {84D0CD72-2EE0-4C89-AE29-615C021779BE}.Release|Win32.ActiveCfg = Release|Win32
+ {84D0CD72-2EE0-4C89-AE29-615C021779BE}.Release|Win32.Build.0 = Release|Win32
+ {84D0CD72-2EE0-4C89-AE29-615C021779BE}.Release|x64.ActiveCfg = Release|x64
+ {84D0CD72-2EE0-4C89-AE29-615C021779BE}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/FlexASIO.vcxproj b/FlexASIO.vcxproj
index 33cc9943..20d36910 100644
--- a/FlexASIO.vcxproj
+++ b/FlexASIO.vcxproj
@@ -169,6 +169,7 @@
+
@@ -180,6 +181,7 @@
+
diff --git a/FlexASIOTest/FlexASIOTest.vcxproj b/FlexASIOTest/FlexASIOTest.vcxproj
new file mode 100644
index 00000000..ae4bbf87
--- /dev/null
+++ b/FlexASIOTest/FlexASIOTest.vcxproj
@@ -0,0 +1,151 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 15.0
+ {84D0CD72-2EE0-4C89-AE29-615C021779BE}
+ FlexASIOTest
+ 10.0.17763.0
+
+
+
+ Application
+ true
+ v141
+ MultiByte
+
+
+ Application
+ false
+ v141
+ true
+ MultiByte
+
+
+ Application
+ true
+ v141
+ MultiByte
+
+
+ Application
+ false
+ v141
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Level4
+ Disabled
+ true
+ true
+ stdcpp17
+ true
+ true
+
+
+ Console
+
+
+
+
+ Level4
+ Disabled
+ true
+ true
+ stdcpp17
+ true
+ true
+
+
+ Console
+
+
+
+
+ Level4
+ MaxSpeed
+ true
+ true
+ true
+ true
+ stdcpp17
+ true
+ true
+
+
+ true
+ true
+ Console
+
+
+
+
+ Level4
+ MaxSpeed
+ true
+ true
+ true
+ true
+ stdcpp17
+ true
+ true
+
+
+ true
+ true
+ Console
+
+
+
+
+
+
+
+ {10c0db40-8f17-4efd-abc5-8dfded9a6910}
+
+
+ {efc61192-2db9-46b1-bf85-98fc6ef1e6d1}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FlexASIOTest/test.cpp b/FlexASIOTest/test.cpp
new file mode 100644
index 00000000..2aea5f4e
--- /dev/null
+++ b/FlexASIOTest/test.cpp
@@ -0,0 +1,70 @@
+#include
+#include
+#include
+
+#include "..\ASIOSDK2.3.1\common\asio.h"
+#include "..\create.h"
+
+// The global ASIO driver pointer that the ASIO host library internally uses.
+extern IASIO* theAsioDriver;
+
+namespace flexasio_test {
+ namespace {
+
+ std::string_view GetASIOErrorString(ASIOError error) {
+ switch (error) {
+ case ASE_OK: return "ASE_OK";
+ case ASE_SUCCESS: return "ASE_SUCCESS";
+ case ASE_NotPresent: return "ASE_NotPresent";
+ case ASE_HWMalfunction: return "ASE_HWMalfunction";
+ case ASE_InvalidParameter: return "ASE_InvalidParameter";
+ case ASE_InvalidMode: return "ASE_InvalidMode";
+ case ASE_SPNotAdvancing: return "ASE_SPNotAdvancing";
+ case ASE_NoClock: return "ASE_NoClock";
+ case ASE_NoMemory: return "ASE_NoMemory";
+ default: return "(unknown ASE error code)";
+ }
+ }
+
+ std::optional Init() {
+ ASIODriverInfo asioDriverInfo = { 0 };
+ asioDriverInfo.asioVersion = 2;
+ std::cout << "ASIOInit(asioVersion = " << asioDriverInfo.asioVersion << ")" << std::endl;
+ const auto initError = ASIOInit(&asioDriverInfo);
+ std::cout << "-> " << GetASIOErrorString(initError) << std::endl;
+ std::cout << "ASIODriverInfo::asioVersion: " << asioDriverInfo.asioVersion << std::endl;
+ std::cout << "ASIODriverInfo::driverVersion: " << asioDriverInfo.asioVersion << std::endl;
+ std::cout << "ASIODriverInfo::name: " << asioDriverInfo.name << std::endl;
+ std::cout << "ASIODriverInfo::errorMessage: " << asioDriverInfo.errorMessage << std::endl;
+ std::cout << "ASIODriverInfo::sysRef: " << asioDriverInfo.sysRef << std::endl;
+ if (initError != ASE_OK) return std::nullopt;
+ return asioDriverInfo;
+ }
+
+ bool Run() {
+ if (!Init()) return false;
+
+ return true;
+ }
+
+ bool InitAndRun() {
+ // This basically does an end run around the ASIO host library driver loading system, simulating what loadAsioDriver() does.
+ // This allows us to trick the ASIO host library into using a specific instance of an ASIO driver (the one this program is linked against),
+ // as opposed to whatever ASIO driver might be currently installed on the system.
+ theAsioDriver = CreateFlexASIO();
+
+ const bool result = Run();
+
+ ReleaseFlexASIO(theAsioDriver);
+ theAsioDriver = nullptr;
+
+ return result;
+ }
+
+ }
+}
+
+int main(int, char**) {
+ if (!::flexasio_test::InitAndRun()) return 1;
+ return 0;
+}
\ No newline at end of file
diff --git a/create.cpp b/create.cpp
new file mode 100644
index 00000000..df4ed613
--- /dev/null
+++ b/create.cpp
@@ -0,0 +1,16 @@
+#include "create.h"
+
+#include
+#include "flexasio.h"
+
+IASIO * CreateFlexASIO() {
+ CFlexASIO * flexASIO = nullptr;
+ assert(CFlexASIO::CreateInstance(&flexASIO) == S_OK);
+ assert(flexASIO != nullptr);
+ return flexASIO;
+}
+
+void ReleaseFlexASIO(IASIO * const iASIO) {
+ assert(iASIO != nullptr);
+ iASIO->Release();
+}
diff --git a/create.h b/create.h
new file mode 100644
index 00000000..381e263d
--- /dev/null
+++ b/create.h
@@ -0,0 +1,6 @@
+#pragma once
+
+struct IASIO;
+
+IASIO * CreateFlexASIO();
+void ReleaseFlexASIO(IASIO *);
diff --git a/dll.def b/dll.def
index a28c5102..47873571 100644
--- a/dll.def
+++ b/dll.def
@@ -1,6 +1,7 @@
; Module-definition file for the FlexASIO DLL
-; Our DLL is just a COM class factory, so we only need to export the functions required by COM.
+; Our DLL is a COM class factory, so we only need to export the functions required by COM.
; We can't use declspec(dllexport) for those because the naming convention doesn't match (leading "@")
+; We also a couple of functions for users that want to instantiate FlexASIO directly (e.g. FlexASIOTest).
LIBRARY
@@ -9,3 +10,5 @@ EXPORTS
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
+ CreateFlexASIO
+ ReleaseFlexASIO