Skip to content

Commit da38aec

Browse files
Merge pull request musescore#18152 from RomanPudashkin/audio_plugin_scanner_various_improvements
audio_plugin_scanner_various_improvements
2 parents eaf847f + 4d2816d commit da38aec

21 files changed

+248
-170
lines changed

src/diagnostics/internal/diagnosticfileswriter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,8 @@ mu::Ret DiagnosticFilesWriter::writeDiagnosticFiles(const path_t& destinationPat
3434
{
3535
TRACEFUNC;
3636

37-
static const std::vector<std::string> DIRS_TO_WRITE {
37+
const std::vector<std::string> DIRS_TO_WRITE {
3838
"logs",
39-
"audio_plugins",
4039
"plugins",
4140
"workspaces",
4241
};
@@ -61,6 +60,7 @@ mu::Ret DiagnosticFilesWriter::writeDiagnosticFiles(const path_t& destinationPat
6160
const std::vector<std::string> FILES_TO_WRITE {
6261
"shortcuts.xml",
6362
"midi_mappings.xml",
63+
"known_audio_plugins.json",
6464
};
6565

6666
for (const std::string& fileName : FILES_TO_WRITE) {

src/framework/audio/audiomodule.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,14 @@ void AudioModule::onInit(const framework::IApplication::RunMode& mode)
191191

192192
// Init configuration
193193
m_configuration->init();
194-
m_soundFontRepository->init();
195194
m_registerAudioPluginsScenario->init();
196195

196+
if (mode == framework::IApplication::RunMode::AudioPluginRegistration) {
197+
return;
198+
}
199+
200+
m_soundFontRepository->init();
201+
197202
m_audioBuffer->init(m_configuration->audioChannelsCount(),
198203
m_configuration->renderStep());
199204

@@ -209,7 +214,7 @@ void AudioModule::onInit(const framework::IApplication::RunMode& mode)
209214
for (const io::path_t& p : paths) {
210215
pr->reg("soundfonts", p);
211216
}
212-
pr->reg("audio_plugins", m_configuration->knownAudioPluginsDir());
217+
pr->reg("known_audio_plugins", m_configuration->knownAudioPluginsFilePath());
213218
}
214219
}
215220

src/framework/audio/audiotypes.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,15 +186,15 @@ struct AudioPluginInfo {
186186
int errorCode = 0;
187187
};
188188

189-
inline AudioPluginType audioPluginTypeFromCategoriesString(const std::string& categoriesStr)
189+
inline AudioPluginType audioPluginTypeFromCategoriesString(const String& categoriesStr)
190190
{
191-
static const std::map<std::string, AudioPluginType> STRING_TO_PLUGIN_TYPE_MAP = {
192-
{ "Fx", AudioPluginType::Fx },
193-
{ "Instrument", AudioPluginType::Instrument },
191+
static const std::map<String, AudioPluginType> STRING_TO_PLUGIN_TYPE_MAP = {
192+
{ u"Fx", AudioPluginType::Fx },
193+
{ u"Instrument", AudioPluginType::Instrument },
194194
};
195195

196196
for (auto it = STRING_TO_PLUGIN_TYPE_MAP.cbegin(); it != STRING_TO_PLUGIN_TYPE_MAP.cend(); ++it) {
197-
if (categoriesStr.find(it->first) != std::string::npos) {
197+
if (categoriesStr.contains(it->first)) {
198198
return it->second;
199199
}
200200
}

src/framework/audio/iaudioconfiguration.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class IAudioConfiguration : MODULE_EXPORT_INTERFACE
7070
virtual async::Notification synthesizerStateChanged() const = 0;
7171
virtual async::Notification synthesizerStateGroupChanged(const std::string& groupName) const = 0;
7272

73-
virtual io::path_t knownAudioPluginsDir() const = 0;
73+
virtual io::path_t knownAudioPluginsFilePath() const = 0;
7474
};
7575
}
7676

src/framework/audio/internal/audioconfiguration.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,9 @@ async::Notification AudioConfiguration::synthesizerStateGroupChanged(const std::
260260
return m_synthesizerStateGroupChanged[gname];
261261
}
262262

263-
io::path_t AudioConfiguration::knownAudioPluginsDir() const
263+
io::path_t AudioConfiguration::knownAudioPluginsFilePath() const
264264
{
265-
return globalConfiguration()->userAppDataPath() + "/audio_plugins";
265+
return globalConfiguration()->userAppDataPath() + "/known_audio_plugins.json";
266266
}
267267

268268
io::path_t AudioConfiguration::stateFilePath() const

src/framework/audio/internal/audioconfiguration.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class AudioConfiguration : public IAudioConfiguration
7070
async::Notification synthesizerStateChanged() const override;
7171
async::Notification synthesizerStateGroupChanged(const std::string& groupName) const override;
7272

73-
io::path_t knownAudioPluginsDir() const override;
73+
io::path_t knownAudioPluginsFilePath() const override;
7474

7575
private:
7676
async::Channel<io::paths_t> m_soundFontDirsChanged;

src/framework/audio/internal/plugins/knownaudiopluginsregister.cpp

Lines changed: 78 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ static JsonObject attributesToJson(const AudioResourceAttributes& attributes)
3838
JsonObject result;
3939

4040
for (auto it = attributes.cbegin(); it != attributes.cend(); ++it) {
41-
if (it->second == audio::PLAYBACK_SETUP_DATA_ATTRIBUTE) {
41+
if (it->first == audio::PLAYBACK_SETUP_DATA_ATTRIBUTE) {
4242
continue;
4343
}
4444

@@ -54,10 +54,17 @@ static JsonObject metaToJson(const AudioResourceMeta& meta)
5454

5555
result.set("id", meta.id);
5656
result.set("type", mu::value(RESOURCE_TYPE_TO_STRING_MAP, meta.type, "Undefined"));
57-
result.set("vendor", meta.vendor);
58-
result.set("attributes", attributesToJson(meta.attributes));
5957
result.set("hasNativeEditorSupport", meta.hasNativeEditorSupport);
6058

59+
if (!meta.vendor.empty()) {
60+
result.set("vendor", meta.vendor);
61+
}
62+
63+
JsonObject attributesJson = attributesToJson(meta.attributes);
64+
if (!attributesJson.empty()) {
65+
result.set("attributes", attributesJson);
66+
}
67+
6168
return result;
6269
}
6370

@@ -79,9 +86,13 @@ static AudioResourceMeta metaFromJson(const JsonObject& object)
7986
result.id = object.value("id").toStdString();
8087
result.type = mu::key(RESOURCE_TYPE_TO_STRING_MAP, object.value("type").toStdString());
8188
result.vendor = object.value("vendor").toStdString();
82-
result.attributes = attributesFromJson(object.value("attributes").toObject());
8389
result.hasNativeEditorSupport = object.value("hasNativeEditorSupport").toBool();
8490

91+
JsonValue attributes = object.value("attributes");
92+
if (attributes.isObject()) {
93+
result.attributes = attributesFromJson(attributes.toObject());
94+
}
95+
8596
return result;
8697
}
8798
}
@@ -90,50 +101,45 @@ mu::Ret KnownAudioPluginsRegister::load()
90101
{
91102
TRACEFUNC;
92103

93-
io::path_t knownAudioPluginsDir = configuration()->knownAudioPluginsDir();
104+
m_loaded = false;
105+
m_pluginInfoMap.clear();
106+
m_pluginPaths.clear();
94107

95-
if (!fileSystem()->exists(knownAudioPluginsDir)) {
96-
fileSystem()->makePath(knownAudioPluginsDir);
108+
io::path_t knownAudioPluginsPath = configuration()->knownAudioPluginsFilePath();
109+
if (!fileSystem()->exists(knownAudioPluginsPath)) {
110+
m_loaded = true;
111+
return make_ok();
97112
}
98113

99-
RetVal<io::paths_t> paths = fileSystem()->scanFiles(knownAudioPluginsDir,
100-
{ "*.json" },
101-
io::ScanMode::FilesInCurrentDir);
102-
if (!paths.ret) {
103-
return paths.ret;
114+
RetVal<ByteArray> file = fileSystem()->readFile(knownAudioPluginsPath);
115+
if (!file.ret) {
116+
return file.ret;
104117
}
105118

106-
m_pluginInfoMap.clear();
107-
m_pluginPaths.clear();
108-
109-
for (const io::path_t& infoPath : paths.val) {
110-
RetVal<ByteArray> file = fileSystem()->readFile(infoPath);
111-
if (!file.ret) {
112-
LOGE() << file.ret.toString();
113-
continue;
114-
}
119+
std::string err;
120+
JsonDocument json = JsonDocument::fromJson(file.val, &err);
121+
if (!err.empty()) {
122+
return Ret(static_cast<int>(Ret::Code::UnknownError), err);
123+
}
115124

116-
std::string err;
117-
JsonDocument json = JsonDocument::fromJson(file.val, &err);
118-
if (!err.empty()) {
119-
LOGE() << err;
120-
continue;
121-
}
125+
JsonArray array = json.rootArray();
122126

123-
JsonObject object = json.rootObject();
127+
for (size_t i = 0; i < array.size(); ++i) {
128+
JsonObject object = array.at(i).toObject();
124129

125130
AudioPluginInfo info;
126131
info.meta = metaFromJson(object.value("meta").toObject());
127-
info.meta.attributes.insert({ audio::PLAYBACK_SETUP_DATA_ATTRIBUTE, mpe::GENERIC_SETUP_DATA_STRING });
128-
info.type = audioPluginTypeFromCategoriesString(info.meta.attributeVal(audio::CATEGORIES_ATTRIBUTE).toStdString());
132+
info.meta.attributes.emplace(audio::PLAYBACK_SETUP_DATA_ATTRIBUTE, mpe::GENERIC_SETUP_DATA_STRING);
133+
info.type = audioPluginTypeFromCategoriesString(info.meta.attributeVal(audio::CATEGORIES_ATTRIBUTE));
129134
info.path = object.value("path").toString();
130135
info.enabled = object.value("enabled").toBool();
131136
info.errorCode = object.value("errorCode").toInt();
132137

133-
m_pluginInfoMap[info.meta.id] = info;
134138
m_pluginPaths.insert(info.path);
139+
m_pluginInfoMap.emplace(info.meta.id, std::move(info));
135140
}
136141

142+
m_loaded = true;
137143
return make_ok();
138144
}
139145

@@ -177,60 +183,69 @@ bool KnownAudioPluginsRegister::exists(const AudioResourceId& resourceId) const
177183

178184
mu::Ret KnownAudioPluginsRegister::registerPlugin(const AudioPluginInfo& info)
179185
{
180-
TRACEFUNC;
181-
182-
JsonObject obj;
183-
obj.set("meta", metaToJson(info.meta));
184-
obj.set("path", info.path.toStdString());
185-
obj.set("enabled", info.enabled);
186-
187-
if (info.errorCode != 0) {
188-
obj.set("errorCode", info.errorCode);
186+
IF_ASSERT_FAILED(m_loaded) {
187+
return false;
189188
}
190189

191-
io::path_t path = pluginInfoPath(info.meta.vendor, info.meta.id);
192-
Ret ret = fileSystem()->writeFile(path, JsonDocument(obj).toJson());
193-
if (!ret) {
194-
return ret;
190+
auto it = m_pluginInfoMap.find(info.meta.id);
191+
if (it != m_pluginInfoMap.end()) {
192+
IF_ASSERT_FAILED(it->second.path != info.path) {
193+
return false;
194+
}
195195
}
196196

197-
m_pluginInfoMap[info.meta.id] = info;
197+
m_pluginInfoMap.emplace(info.meta.id, info);
198198
m_pluginPaths.insert(info.path);
199199

200-
return make_ok();
200+
Ret ret = writePluginsInfo();
201+
return ret;
201202
}
202203

203204
mu::Ret KnownAudioPluginsRegister::unregisterPlugin(const AudioResourceId& resourceId)
204205
{
205-
TRACEFUNC;
206+
IF_ASSERT_FAILED(m_loaded) {
207+
return false;
208+
}
206209

207210
if (!exists(resourceId)) {
208211
return make_ok();
209212
}
210213

211-
AudioPluginInfo info = m_pluginInfoMap[resourceId];
212-
io::path_t path = pluginInfoPath(info.meta.vendor, resourceId);
213-
214-
Ret ret = fileSystem()->remove(path);
215-
if (!ret) {
216-
return ret;
214+
for (const auto& pair : m_pluginInfoMap) {
215+
if (pair.first == resourceId) {
216+
mu::remove(m_pluginPaths, pair.second.path);
217+
}
217218
}
218219

219-
mu::remove(m_pluginInfoMap, resourceId);
220-
mu::remove(m_pluginPaths, info.path);
220+
m_pluginInfoMap.erase(resourceId);
221221

222-
return make_ok();
222+
Ret ret = writePluginsInfo();
223+
return ret;
223224
}
224225

225-
mu::io::path_t KnownAudioPluginsRegister::pluginInfoPath(const AudioResourceVendor& vendor, const AudioResourceId& resourceId) const
226+
mu::Ret KnownAudioPluginsRegister::writePluginsInfo()
226227
{
227-
io::path_t fileName;
228+
TRACEFUNC;
229+
230+
JsonArray array;
231+
232+
for (const auto& pair : m_pluginInfoMap) {
233+
const AudioPluginInfo& info = pair.second;
228234

229-
if (vendor.empty()) {
230-
fileName = io::escapeFileName(resourceId);
231-
} else {
232-
fileName = io::escapeFileName(vendor + "_" + resourceId);
235+
JsonObject obj;
236+
obj.set("meta", metaToJson(info.meta));
237+
obj.set("path", info.path.toStdString());
238+
obj.set("enabled", info.enabled);
239+
240+
if (info.errorCode != 0) {
241+
obj.set("errorCode", info.errorCode);
242+
}
243+
244+
array << obj;
233245
}
234246

235-
return configuration()->knownAudioPluginsDir() + "/" + fileName + ".json";
247+
io::path_t knownAudioPluginsPath = configuration()->knownAudioPluginsFilePath();
248+
Ret ret = fileSystem()->writeFile(knownAudioPluginsPath, JsonDocument(array).toJson());
249+
250+
return ret;
236251
}

src/framework/audio/internal/plugins/knownaudiopluginsregister.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,10 @@ class KnownAudioPluginsRegister : public IKnownAudioPluginsRegister
4848
Ret unregisterPlugin(const AudioResourceId& resourceId) override;
4949

5050
private:
51-
mu::io::path_t pluginInfoPath(const AudioResourceVendor& vendor, const AudioResourceId& resourceId) const;
51+
Ret writePluginsInfo();
5252

53-
std::unordered_map<AudioResourceId, AudioPluginInfo> m_pluginInfoMap;
53+
bool m_loaded = false;
54+
std::multimap<AudioResourceId, AudioPluginInfo> m_pluginInfoMap;
5455
std::set<io::path_t> m_pluginPaths;
5556
};
5657
}

src/framework/audio/internal/plugins/registeraudiopluginsscenario.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ mu::Ret RegisterAudioPluginsScenario::registerPlugin(const io::path_t& pluginPat
129129

130130
for (const AudioResourceMeta& meta : metaList.val) {
131131
AudioPluginInfo info;
132-
info.type = audioPluginTypeFromCategoriesString(meta.attributeVal(audio::CATEGORIES_ATTRIBUTE).toStdString());
132+
info.type = audioPluginTypeFromCategoriesString(meta.attributeVal(audio::CATEGORIES_ATTRIBUTE));
133133
info.meta = meta;
134134
info.path = pluginPath;
135135
info.enabled = true;
@@ -152,7 +152,13 @@ mu::Ret RegisterAudioPluginsScenario::registerFailedPlugin(const io::path_t& plu
152152
}
153153

154154
AudioPluginInfo info;
155-
info.meta.id = io::filename(pluginPath).toStdString();
155+
info.meta.id = io::completeBasename(pluginPath).toStdString();
156+
157+
std::string ext = io::suffix(pluginPath);
158+
if (ext.find("vst") != std::string::npos) {
159+
info.meta.type = AudioResourceType::VstPlugin;
160+
}
161+
156162
info.path = pluginPath;
157163
info.enabled = false;
158164
info.errorCode = failCode;

0 commit comments

Comments
 (0)