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;