diff --git a/muse b/muse
index e573f8bc57ab1..553c5da90153f 160000
--- a/muse
+++ b/muse
@@ -1 +1 @@
-Subproject commit e573f8bc57ab1373d0a80b013e3d3fed932fb7f4
+Subproject commit 553c5da90153fa2ac0e51bc02ce2c4e3fe3272a3
diff --git a/src/converter/internal/compat/notationmeta.cpp b/src/converter/internal/compat/notationmeta.cpp
index 104e899a3040f..1db7154f31c65 100644
--- a/src/converter/internal/compat/notationmeta.cpp
+++ b/src/converter/internal/compat/notationmeta.cpp
@@ -378,9 +378,9 @@ QJsonArray NotationMeta::tracksJsonArray(notation::INotationPtr notation)
QJsonObject jsonTrack;
jsonTrack.insert("instrumentId", trackId.instrumentId.toQString());
jsonTrack.insert("partId", trackId.partId.toQString());
- jsonTrack.insert("type", audioResourceTypeToString(inputParams.resourceMeta.type).toQString());
+ jsonTrack.insert("type", audio::audioResourceTypeToString(inputParams.resourceMeta.type).toQString());
- audio::AudioSourceType sourceType = sourceTypeFromResourceType(inputParams.resourceMeta.type);
+ audio::AudioSourceType sourceType = audio::sourceTypeFromResourceType(inputParams.resourceMeta.type);
if (sourceType != audio::AudioSourceType::Fluid) {
if (sourceType == audio::AudioSourceType::MuseSampler) {
jsonTrack.insert("vendor", QString::fromStdString(inputParams.resourceMeta.attributeVal(
diff --git a/src/notationscene/qml/MuseScore/NotationScene/percussionpanel/percussionpanelmodel.cpp b/src/notationscene/qml/MuseScore/NotationScene/percussionpanel/percussionpanelmodel.cpp
index 6ebd7ab61a776..3f0acffb7a620 100644
--- a/src/notationscene/qml/MuseScore/NotationScene/percussionpanel/percussionpanelmodel.cpp
+++ b/src/notationscene/qml/MuseScore/NotationScene/percussionpanel/percussionpanelmodel.cpp
@@ -553,7 +553,8 @@ void PercussionPanelModel::resetLayout()
}
const muse::audio::AudioResourceMeta& resourceMeta = audioSettings()->trackInputParams(currentTrackId()).resourceMeta;
- const bool isMuseSamplerDrumset = resourceMeta.type == muse::audio::AudioResourceType::MuseSamplerSoundPack;
+ const bool isMuseSamplerDrumset = muse::audio::isResourceType(resourceMeta,
+ muse::audio::AudioResourceType::MuseSamplerSoundPack);
Drumset defaultDrumset = isMuseSamplerDrumset ? museSamplerDefaultDrumset() : standardDefaultDrumset();
@@ -593,7 +594,7 @@ Drumset PercussionPanelModel::museSamplerDefaultDrumset() const
const muse::audio::AudioResourceMeta& resourceMeta = audioSettings()->trackInputParams(currentTrackId()).resourceMeta;
- const int instrumentId = resourceMeta.attributeVal(u"museUID").toInt();
+ const int instrumentId = muse::audio::intAttribute(resourceMeta, u"museUID");
const muse::ByteArray drumMapping = museSampler()->drumMapping(instrumentId);
IF_ASSERT_FAILED(!drumMapping.empty()) {
diff --git a/src/playback/CMakeLists.txt b/src/playback/CMakeLists.txt
index cb7e49ea53f35..89a07db2db8f2 100644
--- a/src/playback/CMakeLists.txt
+++ b/src/playback/CMakeLists.txt
@@ -42,6 +42,10 @@ target_sources(playback PRIVATE
internal/soundprofilesrepository.h
internal/drumsetloader.cpp
internal/drumsetloader.h
+ internal/audiometabridge.cpp
+ internal/audiometabridge.h
+ internal/knownaudiopluginsconfigurator.cpp
+ internal/knownaudiopluginsconfigurator.h
)
if (MUE_BUILD_PLAYBACK_TESTS)
diff --git a/src/playback/internal/audiometabridge.cpp b/src/playback/internal/audiometabridge.cpp
new file mode 100644
index 0000000000000..cebb66aa1c037
--- /dev/null
+++ b/src/playback/internal/audiometabridge.cpp
@@ -0,0 +1,65 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * MuseScore-Studio-CLA-applies
+ *
+ * MuseScore Studio
+ * Music Composition & Notation
+ *
+ * Copyright (C) 2026 MuseScore Limited and others
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "audiometabridge.h"
+
+namespace mu::playback {
+muse::audio::AudioResourceMeta toAudioMeta(const muse::audioplugins::PluginMeta& meta)
+{
+ muse::audio::AudioResourceMeta out;
+ out.id = meta.id;
+ out.vendor = meta.vendor;
+ out.attributes = meta.attributes;
+ out.type = meta.type;
+ return out;
+}
+
+muse::audioplugins::PluginMeta toPluginMeta(const muse::audio::AudioResourceMeta& meta)
+{
+ muse::audioplugins::PluginMeta out;
+ out.id = meta.id;
+ out.vendor = meta.vendor;
+ out.attributes = meta.attributes;
+ out.type = meta.type;
+ return out;
+}
+
+muse::audio::AudioResourceMetaList toAudioMetaList(const muse::audioplugins::PluginMetaList& metas)
+{
+ muse::audio::AudioResourceMetaList out;
+ out.reserve(metas.size());
+ for (const auto& meta : metas) {
+ out.push_back(toAudioMeta(meta));
+ }
+ return out;
+}
+
+muse::audioplugins::PluginMetaList toPluginMetaList(const muse::audio::AudioResourceMetaList& metas)
+{
+ muse::audioplugins::PluginMetaList out;
+ out.reserve(metas.size());
+ for (const auto& meta : metas) {
+ out.push_back(toPluginMeta(meta));
+ }
+ return out;
+}
+}
diff --git a/src/playback/internal/audiometabridge.h b/src/playback/internal/audiometabridge.h
new file mode 100644
index 0000000000000..a3cf031768e33
--- /dev/null
+++ b/src/playback/internal/audiometabridge.h
@@ -0,0 +1,39 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * MuseScore-Studio-CLA-applies
+ *
+ * MuseScore Studio
+ * Music Composition & Notation
+ *
+ * Copyright (C) 2026 MuseScore Limited and others
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+
+#include "audio/common/audiotypes.h"
+#include "audioplugins/audiopluginstypes.h"
+
+// App-side bridge between audio::AudioResourceMeta (engine-domain) and
+// audioplugins::PluginMeta (cache-domain). The framework keeps the two
+// modules independent at the type/interface level; this is where MuseScore
+// converts between them at the natural seam - the playback controller, the
+// project audio settings, the sound profiles repository, etc.
+namespace mu::playback {
+muse::audio::AudioResourceMeta toAudioMeta(const muse::audioplugins::PluginMeta& meta);
+muse::audioplugins::PluginMeta toPluginMeta(const muse::audio::AudioResourceMeta& meta);
+
+muse::audio::AudioResourceMetaList toAudioMetaList(const muse::audioplugins::PluginMetaList& metas);
+muse::audioplugins::PluginMetaList toPluginMetaList(const muse::audio::AudioResourceMetaList& metas);
+}
diff --git a/src/playback/internal/drumsetloader.cpp b/src/playback/internal/drumsetloader.cpp
index 3e4d336b1cc1c..b5dd2a140d226 100644
--- a/src/playback/internal/drumsetloader.cpp
+++ b/src/playback/internal/drumsetloader.cpp
@@ -41,7 +41,7 @@ void DrumsetLoader::loadDrumset(INotationPtr notation, const InstrumentTrackId&
}
// restore the default drumset when changing from MuseSounds to MS Basic / VST
- if (resourceMeta.type != AudioResourceType::MuseSamplerSoundPack) {
+ if (!isResourceType(resourceMeta, AudioResourceType::MuseSamplerSoundPack)) {
const InstrumentTemplate& templ = instrumentsRepository()->instrumentTemplate(trackId.instrumentId);
if (!templ.useDrumset) {
return;
@@ -56,7 +56,7 @@ void DrumsetLoader::loadDrumset(INotationPtr notation, const InstrumentTrackId&
return;
}
- int instrumentId = resourceMeta.attributeVal(u"museUID").toInt();
+ int instrumentId = muse::audio::intAttribute(resourceMeta, u"museUID");
auto it = m_drumsetCache.find(instrumentId);
if (it != m_drumsetCache.end()) {
diff --git a/src/playback/internal/knownaudiopluginsconfigurator.cpp b/src/playback/internal/knownaudiopluginsconfigurator.cpp
new file mode 100644
index 0000000000000..65308f3f231c9
--- /dev/null
+++ b/src/playback/internal/knownaudiopluginsconfigurator.cpp
@@ -0,0 +1,81 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * MuseScore-Studio-CLA-applies
+ *
+ * MuseScore Studio
+ * Music Composition & Notation
+ *
+ * Copyright (C) 2026 MuseScore Limited and others
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#include "knownaudiopluginsconfigurator.h"
+
+#include "global/serialization/json.h"
+
+#include "audio/common/audiotypes.h"
+#include "mpe/playbacksetupdata.h"
+
+using namespace mu::playback;
+using namespace muse::audioplugins;
+
+void KnownAudioPluginsConfigurator::init()
+{
+ if (m_audioPluginConfiguration()) {
+ // MuseScore's audio engine routes synthesis via the playbackSetupData
+ // attribute. It is runtime-only — the engine re-injects the generic
+ // default at every load, so the cache file should not persist it.
+ PluginAttributes runtimeDefaults;
+ runtimeDefaults.emplace(muse::audio::PLAYBACK_SETUP_DATA_ATTRIBUTE,
+ muse::mpe::GENERIC_SETUP_DATA_STRING);
+ m_audioPluginConfiguration()->setRuntimeAttributeDefaults(runtimeDefaults);
+ }
+
+ // MuseScore-specific audioplugins migrations only — framework-owned
+ // steps (v0->v1 structural, v1->v2 enabled->state) are pre-registered
+ // by the framework's AudioPluginsModule.
+ if (m_migrationRegister()) {
+ // v2 → v3: hasNativeEditorSupport moved from a top-level meta field
+ // into meta.attributes (string "true"/"false"). MuseScore-specific:
+ // audacity has no native-editor concept.
+ m_migrationRegister()->registerMigration(2, [](const muse::JsonArray& plugins) {
+ const std::string nativeEditorKey = muse::audio::HAS_NATIVE_EDITOR_SUPPORT_ATTRIBUTE.toStdString();
+ muse::JsonArray out;
+ for (size_t i = 0; i < plugins.size(); ++i) {
+ muse::JsonObject obj = plugins.at(i).toObject();
+ muse::JsonObject meta = obj.value("meta").toObject();
+ if (meta.contains(nativeEditorKey)) {
+ muse::JsonObject attrs;
+ if (meta.contains("attributes")) {
+ attrs = meta.value("attributes").toObject();
+ }
+ const bool b = meta.value(nativeEditorKey).toBool();
+ attrs.set(nativeEditorKey, b ? std::string("true") : std::string("false"));
+ meta.set("attributes", attrs);
+
+ // JsonObject has no remove(); rebuild without the legacy key.
+ muse::JsonObject metaWithoutLegacy;
+ for (const std::string& k : meta.keys()) {
+ if (k == nativeEditorKey) {
+ continue;
+ }
+ metaWithoutLegacy.set(k, meta.value(k));
+ }
+ obj.set("meta", metaWithoutLegacy);
+ }
+ out << obj;
+ }
+ return out;
+ });
+ }
+}
diff --git a/src/playback/internal/knownaudiopluginsconfigurator.h b/src/playback/internal/knownaudiopluginsconfigurator.h
new file mode 100644
index 0000000000000..d43e3bd489c17
--- /dev/null
+++ b/src/playback/internal/knownaudiopluginsconfigurator.h
@@ -0,0 +1,42 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * MuseScore-Studio-CLA-applies
+ *
+ * MuseScore Studio
+ * Music Composition & Notation
+ *
+ * Copyright (C) 2026 MuseScore Limited and others
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#pragma once
+
+#include "modularity/ioc.h"
+
+#include "audioplugins/iaudiopluginsconfiguration.h"
+#include "audioplugins/iknownaudiopluginsmigrationregister.h"
+
+namespace mu::playback {
+// MuseScore-specific configuration of the framework's shared known-audio-plugins
+// cache: marks runtime-only attributes and registers the app's cache migration.
+// Not a module — it's one-shot setup invoked from PlaybackModule::resolveImports()
+// (before the cache is loaded in the audioplugins context onInit).
+class KnownAudioPluginsConfigurator
+{
+ muse::GlobalInject m_audioPluginConfiguration;
+ muse::GlobalInject m_migrationRegister;
+
+public:
+ void init();
+};
+}
diff --git a/src/playback/internal/playbackcontroller.cpp b/src/playback/internal/playbackcontroller.cpp
index 5cb6641790b6e..90fc311629bd4 100644
--- a/src/playback/internal/playbackcontroller.cpp
+++ b/src/playback/internal/playbackcontroller.cpp
@@ -493,7 +493,8 @@ bool PlaybackController::shouldLoadDrumset(const engraving::InstrumentTrackId& i
return false;
}
- return oldMeta.type == AudioResourceType::MuseSamplerSoundPack || newMeta.type == AudioResourceType::MuseSamplerSoundPack;
+ return isResourceType(oldMeta, AudioResourceType::MuseSamplerSoundPack)
+ || isResourceType(newMeta, AudioResourceType::MuseSamplerSoundPack);
}
void PlaybackController::addSoundFlagsIfNeed(const std::vector& selection)
diff --git a/src/playback/internal/soundprofilesrepository.cpp b/src/playback/internal/soundprofilesrepository.cpp
index 7e6eca6cd6800..890793692e21c 100644
--- a/src/playback/internal/soundprofilesrepository.cpp
+++ b/src/playback/internal/soundprofilesrepository.cpp
@@ -67,11 +67,11 @@ void SoundProfilesRepository::refresh()
continue;
}
- if (resource.type == AudioResourceType::FluidSoundfont) {
+ if (isResourceType(resource, AudioResourceType::FluidSoundfont)) {
basicProfile.data.emplace(mpe::PlaybackSetupData::fromString(setup->second), resource);
}
- if (resource.type == AudioResourceType::MuseSamplerSoundPack) {
+ if (isResourceType(resource, AudioResourceType::MuseSamplerSoundPack)) {
museProfile.data.emplace(mpe::PlaybackSetupData::fromString(setup->second), resource);
}
}
diff --git a/src/playback/playbackmodule.cpp b/src/playback/playbackmodule.cpp
index 3fc0d6ade5f50..1ea510fc2c06f 100644
--- a/src/playback/playbackmodule.cpp
+++ b/src/playback/playbackmodule.cpp
@@ -33,6 +33,7 @@
#include "internal/playbackcommands.h"
#include "internal/playbackconfiguration.h"
#include "internal/soundprofilesrepository.h"
+#include "internal/knownaudiopluginsconfigurator.h"
using namespace mu::playback;
using namespace muse;
@@ -64,6 +65,11 @@ void PlaybackModule::resolveImports()
if (cr) {
cr->reg(std::make_shared());
}
+
+ // MuseScore-specific setup of the shared known-audio-plugins cache. Must run
+ // before the cache is loaded in the audioplugins context onInit — resolveImports
+ // of every module precedes any onInit, so this is the right phase.
+ KnownAudioPluginsConfigurator().init();
}
void PlaybackModule::onInit(const IApplication::RunMode&)
diff --git a/src/playback/qml/MuseScore/Playback/inputresourceitem.cpp b/src/playback/qml/MuseScore/Playback/inputresourceitem.cpp
index 7b2b68dc41b1c..cdf2784c4cc49 100644
--- a/src/playback/qml/MuseScore/Playback/inputresourceitem.cpp
+++ b/src/playback/qml/MuseScore/Playback/inputresourceitem.cpp
@@ -64,7 +64,7 @@ static QString makeMenuResourceItemId(AudioResourceType type, const QString& res
return str + "\\" + resourceId;
}
-static void parseAudioResourceTypeAndId(const QString& menuItemId, AudioResourceType& type, AudioResourceId& resourceId)
+static void parseAudioResourceTypeAndId(const QString& menuItemId, AudioResourceType& type, audioplugins::PluginResourceId& resourceId)
{
QString typeStr = menuItemId.section("\\", 0, 0);
type = muse::key(AUDIO_RESOURCE_TYPE_TO_STR, typeStr);
@@ -87,9 +87,11 @@ void InputResourceItem::requestAvailableResources()
if (!isBlank()) {
QString currentResourceId = QString::fromStdString(m_currentInputParams.resourceMeta.id);
- result << buildMenuItem(makeMenuResourceItemId(m_currentInputParams.resourceMeta.type, currentResourceId),
- title(),
- /*checked*/ true, /*subItems*/ QVariantList(), /*includeInFilteredLists*/ false);
+ result <<
+ buildMenuItem(makeMenuResourceItemId(muse::audio::resourceTypeFromString(m_currentInputParams.resourceMeta.type),
+ currentResourceId),
+ title(),
+ /*checked*/ true, /*subItems*/ QVariantList(), /*includeInFilteredLists*/ false);
result << buildSeparator();
}
@@ -137,7 +139,7 @@ void InputResourceItem::handleMenuItem(const QString& menuItemId)
}
AudioResourceType newResourceType = AudioResourceType::Undefined;
- AudioResourceId newResourceId;
+ audioplugins::PluginResourceId newResourceId;
parseAudioResourceTypeAndId(menuItemId, newResourceType, newResourceId);
auto resourcesIt = m_availableResourceMap.find(newResourceType);
@@ -208,7 +210,7 @@ bool InputResourceItem::isActive() const
bool InputResourceItem::hasNativeEditorSupport() const
{
- return m_currentInputParams.resourceMeta.hasNativeEditorSupport;
+ return muse::audio::hasNativeEditorSupport(m_currentInputParams.resourceMeta);
}
QVariantMap InputResourceItem::buildMuseMenuItem(const ResourceByVendorMap& resourcesByVendor) const
@@ -300,7 +302,8 @@ QVariantMap InputResourceItem::buildMuseMenuItem(const ResourceByVendorMap& reso
return buildMenuItem(MUSE_MENU_ITEM_ID,
MUSE_MENU_ITEM_ID,
- m_currentInputParams.resourceMeta.type == AudioResourceType::MuseSamplerSoundPack,
+ muse::audio::isResourceType(m_currentInputParams.resourceMeta,
+ muse::audio::AudioResourceType::MuseSamplerSoundPack),
subItemsByType,
/*includeInFilteredLists*/ false);
}
@@ -314,7 +317,7 @@ QVariantMap InputResourceItem::buildVstMenuItem(const ResourceByVendorMap& resou
for (const AudioResourceMeta& resourceMeta : pair.second) {
QString resourceId = QString::fromStdString(resourceMeta.id);
- subItemsByVendor << buildMenuItem(makeMenuResourceItemId(resourceMeta.type, resourceId),
+ subItemsByVendor << buildMenuItem(makeMenuResourceItemId(muse::audio::resourceTypeFromString(resourceMeta.type), resourceId),
resourceId,
m_currentInputParams.resourceMeta.id == resourceMeta.id);
}
@@ -330,7 +333,8 @@ QVariantMap InputResourceItem::buildVstMenuItem(const ResourceByVendorMap& resou
return buildMenuItem(VST_MENU_ITEM_ID,
VST_MENU_ITEM_ID,
- m_currentInputParams.resourceMeta.type == AudioResourceType::VstPlugin,
+ muse::audio::isResourceType(m_currentInputParams.resourceMeta,
+ muse::audio::AudioResourceType::VstPlugin),
subItemsByType,
/*includeInFilteredLists*/ false);
}
@@ -391,7 +395,8 @@ QVariantMap InputResourceItem::buildSoundFontsMenuItem(const ResourceByVendorMap
return buildMenuItem(SOUNDFONTS_MENU_ITEM_ID,
muse::qtrc("playback", "SoundFonts"),
- m_currentInputParams.resourceMeta.type == AudioResourceType::FluidSoundfont,
+ muse::audio::isResourceType(m_currentInputParams.resourceMeta,
+ muse::audio::AudioResourceType::FluidSoundfont),
soundFontItems,
/*includeInFilteredLists*/ false);
}
@@ -436,7 +441,8 @@ QVariantMap InputResourceItem::buildMsBasicMenuItem(const AudioResourceMetaList&
presetName = muse::qtrc("playback", "Bank %1, preset %2").arg(item.preset.bank).arg(item.preset.program);
}
- return buildMenuItem(makeMenuResourceItemId(resourceMeta.type, QString::fromStdString(resourceMeta.id)),
+ return buildMenuItem(makeMenuResourceItemId(muse::audio::resourceTypeFromString(resourceMeta.type),
+ QString::fromStdString(resourceMeta.id)),
presetName,
isCurrent);
}
@@ -487,7 +493,8 @@ QVariantMap InputResourceItem::buildMsBasicMenuItem(const AudioResourceMetaList&
// Prepend the "Choose automatically" item
categoryItems.prepend(buildSeparator());
- categoryItems.prepend(buildMenuItem(makeMenuResourceItemId(chooseAutomaticMeta.type, QString::fromStdString(chooseAutomaticMeta.id)),
+ categoryItems.prepend(buildMenuItem(makeMenuResourceItemId(muse::audio::resourceTypeFromString(chooseAutomaticMeta.type),
+ QString::fromStdString(chooseAutomaticMeta.id)),
muse::qtrc("playback", "Choose automatically"),
isCurrentSoundFont && !currentPreset.has_value(),
/*subItems*/ QVariantList(),
@@ -552,7 +559,8 @@ QVariantMap InputResourceItem::buildSoundFontMenuItem(const muse::String& soundF
// Prepend the "Choose automatically" item
bankItems.prepend(buildSeparator());
- bankItems.prepend(buildMenuItem(makeMenuResourceItemId(chooseAutomaticMeta.type, QString::fromStdString(chooseAutomaticMeta.id)),
+ bankItems.prepend(buildMenuItem(makeMenuResourceItemId(muse::audio::resourceTypeFromString(chooseAutomaticMeta.type),
+ QString::fromStdString(chooseAutomaticMeta.id)),
muse::qtrc("playback", "Choose automatically"),
isCurrentSoundFont && !currentPreset.has_value(),
/*subItems*/ QVariantList(),
@@ -571,7 +579,7 @@ void InputResourceItem::updateAvailableResources(const AudioResourceMetaList& av
m_availableResourceMap.clear();
for (const AudioResourceMeta& meta : availableResources) {
- ResourceByVendorMap& resourcesByVendor = m_availableResourceMap[meta.type];
+ ResourceByVendorMap& resourcesByVendor = m_availableResourceMap[muse::audio::resourceTypeFromString(meta.type)];
AudioResourceMetaList& resourcesMetaList = resourcesByVendor[meta.vendor];
resourcesMetaList.push_back(meta);
}
diff --git a/src/playback/qml/MuseScore/Playback/outputresourceitem.cpp b/src/playback/qml/MuseScore/Playback/outputresourceitem.cpp
index 7b97dd0121341..977880afed9d6 100644
--- a/src/playback/qml/MuseScore/Playback/outputresourceitem.cpp
+++ b/src/playback/qml/MuseScore/Playback/outputresourceitem.cpp
@@ -3,6 +3,7 @@
#include
#include "audio/common/audioutils.h"
+#include "vst/vstpluginattrs.h"
#include "log.h"
#include "translation.h"
@@ -103,7 +104,7 @@ void OutputResourceItem::handleMenuItem(const QString& menuItemId)
return;
}
- const AudioResourceId& newSelectedResourceId = menuItemId.toStdString();
+ const audioplugins::PluginResourceId& newSelectedResourceId = menuItemId.toStdString();
for (const auto& pair : m_fxByVendorMap) {
for (const AudioResourceMeta& fxResourceMeta : pair.second) {
@@ -183,7 +184,7 @@ void OutputResourceItem::updateCurrentFxParams(const AudioResourceMeta& newMeta)
requestToCloseNativeEditorView();
audio::AudioFxParams newParams = m_currentFxParams;
- newParams.categories = audio::audioFxCategoriesFromString(newMeta.attributeVal(audio::CATEGORIES_ATTRIBUTE));
+ newParams.categories = audio::audioFxCategoriesFromString(newMeta.attributeVal(vst::CATEGORIES_ATTRIBUTE));
newParams.resourceMeta = newMeta;
newParams.configuration.clear();
newParams.active = newMeta.isValid();
@@ -213,5 +214,5 @@ bool OutputResourceItem::isBlank() const
bool OutputResourceItem::hasNativeEditorSupport() const
{
- return m_currentFxParams.resourceMeta.hasNativeEditorSupport;
+ return muse::audio::hasNativeEditorSupport(m_currentFxParams.resourceMeta);
}
diff --git a/src/project/internal/projectaudiosettings.cpp b/src/project/internal/projectaudiosettings.cpp
index fb33b56003a20..a2d4dd09adac1 100644
--- a/src/project/internal/projectaudiosettings.cpp
+++ b/src/project/internal/projectaudiosettings.cpp
@@ -29,6 +29,7 @@
#include "types/bytearray.h"
#include "audio/common/audioutils.h"
+#include "vst/vstpluginattrs.h"
using namespace mu::project;
using namespace muse;
@@ -45,7 +46,7 @@ static const std::map SOURCE_TYPE_MAP = {
static void doCompatibilityConversions(AudioResourceMeta& meta)
{
- if (meta.type == AudioResourceType::MuseSamplerSoundPack) {
+ if (isResourceType(meta, AudioResourceType::MuseSamplerSoundPack)) {
// MS 4.5: resource name and category have been excluded from ID
// Old format: category\\name\\uid
if (meta.id.find("\\") == std::string::npos) {
@@ -380,7 +381,7 @@ AudioFxParams ProjectAudioSettings::fxParamsFromJson(const QJsonObject& object)
result.chainOrder = static_cast(object.value("chainOrder").toInt());
result.resourceMeta = resourceMetaFromJson(object.value("resourceMeta").toObject());
result.configuration = unitConfigFromJson(object.value("unitConfiguration").toObject());
- result.categories = audioFxCategoriesFromString(result.resourceMeta.attributeVal(audio::CATEGORIES_ATTRIBUTE));
+ result.categories = audioFxCategoriesFromString(result.resourceMeta.attributeVal(vst::CATEGORIES_ATTRIBUTE));
return result;
}
@@ -410,11 +411,18 @@ AudioResourceMeta ProjectAudioSettings::resourceMetaFromJson(const QJsonObject&
{
AudioResourceMeta result;
result.id = object.value("id").toString().toStdString();
- result.hasNativeEditorSupport = object.value("hasNativeEditorSupport").toBool();
result.vendor = object.value("vendor").toString().toStdString();
result.type = resourceTypeFromString(object.value("type").toString());
result.attributes = attributesFromJson(object.value("attributes").toObject());
+ // Migrate the legacy top-level "hasNativeEditorSupport" boolean into attributes
+ // for project files written before audio plugin cache version 1.
+ const QString nativeEditorKey = audio::HAS_NATIVE_EDITOR_SUPPORT_ATTRIBUTE.toQString();
+ if (object.contains(nativeEditorKey) && !result.attributes.count(audio::HAS_NATIVE_EDITOR_SUPPORT_ATTRIBUTE)) {
+ const bool b = object.value(nativeEditorKey).toBool();
+ result.attributes.emplace(audio::HAS_NATIVE_EDITOR_SUPPORT_ATTRIBUTE, b ? u"true" : u"false");
+ }
+
return result;
}
@@ -519,7 +527,6 @@ QJsonObject ProjectAudioSettings::resourceMetaToJson(const AudioResourceMeta& me
{
QJsonObject result;
result.insert("id", QString::fromStdString(meta.id));
- result.insert("hasNativeEditorSupport", meta.hasNativeEditorSupport);
result.insert("vendor", QString::fromStdString(meta.vendor));
result.insert("type", audioResourceTypeToString(meta.type).toQString());
result.insert("attributes", attributesToJson(meta.attributes));
@@ -561,15 +568,15 @@ AudioSourceType ProjectAudioSettings::sourceTypeFromString(const QString& string
return AudioSourceType::Undefined;
}
-AudioResourceType ProjectAudioSettings::resourceTypeFromString(const QString& string) const
+audioplugins::PluginType ProjectAudioSettings::resourceTypeFromString(const QString& string) const
{
for (const auto& pair : RESOURCE_TYPE_MAP) {
if (pair.second == string) {
- return pair.first;
+ return audio::resourceTypeName(pair.first);
}
}
- return AudioResourceType::Undefined;
+ return audioplugins::PluginType();
}
QString ProjectAudioSettings::sourceTypeToString(const AudioSourceType& type) const
diff --git a/src/project/internal/projectaudiosettings.h b/src/project/internal/projectaudiosettings.h
index eda61bf16ed54..0c2be1b0fa898 100644
--- a/src/project/internal/projectaudiosettings.h
+++ b/src/project/internal/projectaudiosettings.h
@@ -101,7 +101,7 @@ class ProjectAudioSettings : public IProjectAudioSettings, public muse::Contexta
QJsonObject attributesToJson(const muse::audio::AudioResourceAttributes& attributes) const;
muse::audio::AudioSourceType sourceTypeFromString(const QString& string) const;
- muse::audio::AudioResourceType resourceTypeFromString(const QString& string) const;
+ muse::audioplugins::PluginType resourceTypeFromString(const QString& string) const;
QString sourceTypeToString(const muse::audio::AudioSourceType& type) const;