forked from eiz/SynchronousAudioRouter
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtinyasio.cpp
More file actions
125 lines (97 loc) · 3.48 KB
/
tinyasio.cpp
File metadata and controls
125 lines (97 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// SynchronousAudioRouter
// Copyright (C) 2015 Mackenzie Straight
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SynchronousAudioRouter. If not, see <http://www.gnu.org/licenses/>.
#include "tinyasio.h"
#include <vector>
#include <iostream>
#include <string>
#include <locale>
#include <codecvt>
#define LOG(...) std::cout << std::endl
#ifndef UNICODE
#error "SarAsio must be built with unicode"
#endif
namespace Sar {
static std::string TCHARToUTF8(const TCHAR *ptr)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
return converter.to_bytes(ptr);
}
static std::wstring UTF8ToWide(const std::string& str)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
return converter.from_bytes(str);
}
std::vector<AsioDriver> InstalledAsioDrivers()
{
std::vector<AsioDriver> result;
HKEY asio;
DWORD index = 0, nameSize = 256, valueSize = 256;
LONG err;
TCHAR name[256], value[256];
LOG(INFO) << "Querying installed ASIO drivers.";
if (!SUCCEEDED(err = RegOpenKeyEx(
HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\ASIO"), 0, KEY_READ, &asio))) {
LOG(INFO) << "Failed to open HKLM\\SOFTWARE\\ASIO: status " << err;
return result;
}
while ((err = RegEnumKeyEx(
asio, index++, name, &nameSize, nullptr, nullptr, nullptr, nullptr)) ==
ERROR_SUCCESS) {
AsioDriver driver;
nameSize = 256;
valueSize = 256;
if ((err = RegGetValue(
asio, name, TEXT("CLSID"), RRF_RT_REG_SZ,
nullptr, value, &valueSize)) != ERROR_SUCCESS) {
LOG(INFO) << "Skipping key "
<< TCHARToUTF8(name) << ": Couldn't get CLSID, error "
<< err;
continue;
}
driver.clsid = TCHARToUTF8(value);
valueSize = 256;
if (RegGetValue(
asio, name, TEXT("Description"), RRF_RT_REG_SZ,
nullptr, value, &valueSize) != ERROR_SUCCESS) {
// Workaround for drivers with incomplete ASIO registration.
// Observed with M-Audio drivers: the main (64bit) registration is
// fine but the Wow6432Node version is missing the description.
LOG(INFO) << "Unable to get ASIO driver description, using key name instead.";
driver.name = TCHARToUTF8(name);
} else {
driver.name = TCHARToUTF8(value);
}
LOG(INFO) << "Found ASIO driver: " << driver.name
<< " with CLSID " << driver.clsid;
result.emplace_back(driver);
}
LOG(INFO) << "Done querying ASIO drivers. Status: " << err;
RegCloseKey(asio);
return result;
}
HRESULT AsioDriver::open(IASIO **ppAsio)
{
HRESULT status;
auto wstr = UTF8ToWide(clsid);
GUID clsid;
status = CLSIDFromString(wstr.c_str(), &clsid);
if (!SUCCEEDED(status)) {
return status;
}
return CoCreateInstance(
clsid, nullptr, CLSCTX_INPROC_SERVER, clsid, (LPVOID *)ppAsio);
}
} // namespace Sar