Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion muse
Submodule muse updated 47 files
+69 −68 framework/audio/common/audiotypes.h
+7 −17 framework/audio/common/audioutils.h
+2 −2 framework/audio/common/rpc/rpcpacker.h
+1 −2 framework/audio/engine/internal/audioengineconfiguration.cpp
+1 −3 framework/audio/engine/internal/enginerpccontroller.cpp
+2 −4 framework/audio/engine/internal/synthesizers/fluidsynth/fluidresolver.cpp
+1 −0 framework/audio/tests/CMakeLists.txt
+91 −0 framework/audio/tests/audioresourcetypes_tests.cpp
+5 −6 framework/audio/tests/rpcpacker_tests.cpp
+3 −1 framework/audioplugins/CMakeLists.txt
+3 −1 framework/audioplugins/audiopluginsmodule.cpp
+137 −7 framework/audioplugins/audiopluginstypes.h
+3 −3 framework/audioplugins/iaudiopluginmetareader.h
+9 −0 framework/audioplugins/iaudiopluginsconfiguration.h
+46 −0 framework/audioplugins/iknownaudiopluginsmigrationregister.h
+11 −3 framework/audioplugins/iknownaudiopluginsregister.h
+10 −0 framework/audioplugins/internal/audiopluginsconfiguration.cpp
+6 −0 framework/audioplugins/internal/audiopluginsconfiguration.h
+104 −0 framework/audioplugins/internal/knownaudiopluginsmigrationregister.cpp
+12 −14 framework/audioplugins/internal/knownaudiopluginsmigrationregister.h
+124 −27 framework/audioplugins/internal/knownaudiopluginsregister.cpp
+10 −4 framework/audioplugins/internal/knownaudiopluginsregister.h
+129 −25 framework/audioplugins/internal/registeraudiopluginsscenario.cpp
+4 −3 framework/audioplugins/internal/registeraudiopluginsscenario.h
+12 −5 framework/audioplugins/iregisteraudiopluginsscenario.h
+2 −1 framework/audioplugins/tests/CMakeLists.txt
+0 −52 framework/audioplugins/tests/audiopluginsutilstest.cpp
+312 −0 framework/audioplugins/tests/knownaudiopluginsmigrationregistertest.cpp
+198 −37 framework/audioplugins/tests/knownaudiopluginsregistertest.cpp
+2 −2 framework/audioplugins/tests/mocks/audiopluginmetareadermock.h
+3 −0 framework/audioplugins/tests/mocks/audiopluginsconfigurationmock.h
+35 −0 framework/audioplugins/tests/mocks/knownaudiopluginsmigrationregistermock.h
+7 −3 framework/audioplugins/tests/mocks/knownaudiopluginsregistermock.h
+338 −24 framework/audioplugins/tests/registeraudiopluginsscenariotest.cpp
+1 −1 framework/musesampler/internal/musesamplerresolver.cpp
+4 −0 framework/musesampler/musesamplertypes.h
+1 −0 framework/vst/CMakeLists.txt
+1 −1 framework/vst/internal/fx/vstfxprocessor.cpp
+1 −1 framework/vst/internal/synth/vstsynthesiser.cpp
+4 −4 framework/vst/internal/vstaudioclient.cpp
+2 −4 framework/vst/internal/vstaudioclient.h
+10 −4 framework/vst/internal/vstmodulesrepository.cpp
+1 −2 framework/vst/internal/vstmodulesrepository.h
+10 −7 framework/vst/internal/vstpluginmetareader.cpp
+2 −2 framework/vst/internal/vstpluginmetareader.h
+40 −0 framework/vst/vstpluginattrs.h
+8 −0 framework/vst/vsttypes.h
3 changes: 3 additions & 0 deletions src/app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,9 @@ set(APP_SRC
appfactory.cpp
appfactory.h

internal/audiopluginsappconfigmodule.cpp
internal/audiopluginsappconfigmodule.h

internal/guiapp.cpp
internal/guiapp.h
)
Expand Down
4 changes: 4 additions & 0 deletions src/app/appfactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#ifdef MUSE_MODULE_AUDIOPLUGINS
#include "framework/audioplugins/audiopluginsmodule.h"
#include "internal/audiopluginsappconfigmodule.h"
#endif

#ifdef MUSE_MODULE_CLOUD
Expand Down Expand Up @@ -314,6 +315,7 @@ std::shared_ptr<muse::IApplication> AppFactory::newGuiApp(const std::shared_ptr<
app->addModule(new muse::audio::AudioModule());
#ifdef MUSE_MODULE_AUDIOPLUGINS
app->addModule(new muse::audioplugins::AudioPluginsModule());
app->addModule(new mu::app::AudioPluginsAppConfigModule());
#endif
app->addModule(new muse::automation::AutomationModule());
app->addModule(new muse::draw::DrawModule());
Expand Down Expand Up @@ -455,6 +457,7 @@ static void addConsoleModules(std::shared_ptr<MuseScoreConsoleApp> app)
app->addModule(new muse::audio::AudioModule());
#ifdef MUSE_MODULE_AUDIOPLUGINS
app->addModule(new muse::audioplugins::AudioPluginsModule());
app->addModule(new mu::app::AudioPluginsAppConfigModule());
#endif
app->addModule(new muse::draw::DrawModule());
app->addModule(new muse::midi::MidiModule());
Expand Down Expand Up @@ -547,6 +550,7 @@ static void addAudioPluginRegistrationModules(std::shared_ptr<MuseScoreConsoleAp

#ifdef MUSE_MODULE_AUDIOPLUGINS
app->addModule(new muse::audioplugins::AudioPluginsModule());
app->addModule(new mu::app::AudioPluginsAppConfigModule());
#endif

#ifdef MUSE_MODULE_VST
Expand Down
95 changes: 95 additions & 0 deletions src/app/internal/audiopluginsappconfigmodule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "audiopluginsappconfigmodule.h"

#include "modularity/ioc.h"

#include "global/serialization/json.h"

#include "audio/common/audiotypes.h"
#include "mpe/playbacksetupdata.h"

#include "audioplugins/iaudiopluginsconfiguration.h"
#include "audioplugins/iknownaudiopluginsmigrationregister.h"

using namespace mu::app;
using namespace muse::audioplugins;

static const std::string mname("audiopluginsappconfig");

std::string AudioPluginsAppConfigModule::moduleName() const
{
return mname;
}

void AudioPluginsAppConfigModule::resolveImports()
{
auto configuration = muse::modularity::globalIoc()->resolve<IAudioPluginsConfiguration>(moduleName());
if (configuration) {
// 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.
AudioResourceAttributes runtimeDefaults;
runtimeDefaults.emplace(muse::audio::PLAYBACK_SETUP_DATA_ATTRIBUTE,
muse::mpe::GENERIC_SETUP_DATA_STRING);
configuration->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.
auto migrations = muse::modularity::globalIoc()->resolve<IKnownAudioPluginsMigrationRegister>(moduleName());
if (migrations) {
// v2 → v3: hasNativeEditorSupport moved from a top-level meta field
// into meta.attributes (string "true"/"false"). MuseScore-specific:
// audacity has no native-editor concept.
migrations->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;
});
}
}
33 changes: 33 additions & 0 deletions src/app/internal/audiopluginsappconfigmodule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
#pragma once

#include "modularity/imodulesetup.h"

namespace mu::app {
class AudioPluginsAppConfigModule : public muse::modularity::IModuleSetup
{
public:
std::string moduleName() const override;
void resolveImports() override;
};
}
4 changes: 2 additions & 2 deletions src/converter/internal/compat/notationmeta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,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();

Expand Down Expand Up @@ -594,7 +595,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::audioplugins::intAttribute(resourceMeta, u"museUID");

const muse::ByteArray drumMapping = museSampler()->drumMapping(instrumentId);
IF_ASSERT_FAILED(!drumMapping.empty()) {
Expand Down
4 changes: 2 additions & 2 deletions src/playback/internal/drumsetloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -56,7 +56,7 @@ void DrumsetLoader::loadDrumset(INotationPtr notation, const InstrumentTrackId&
return;
}

int instrumentId = resourceMeta.attributeVal(u"museUID").toInt();
int instrumentId = muse::audioplugins::intAttribute(resourceMeta, u"museUID");

auto it = m_drumsetCache.find(instrumentId);
if (it != m_drumsetCache.end()) {
Expand Down
3 changes: 2 additions & 1 deletion src/playback/internal/playbackcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,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<EngravingItem*>& selection)
Expand Down
4 changes: 2 additions & 2 deletions src/playback/internal/soundprofilesrepository.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
32 changes: 20 additions & 12 deletions src/playback/qml/MuseScore/Playback/inputresourceitem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand All @@ -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);
}
Expand Down
5 changes: 3 additions & 2 deletions src/playback/qml/MuseScore/Playback/outputresourceitem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <QList>

#include "audio/common/audioutils.h"
#include "vst/vstpluginattrs.h"

#include "log.h"
#include "translation.h"
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -213,5 +214,5 @@ bool OutputResourceItem::isBlank() const

bool OutputResourceItem::hasNativeEditorSupport() const
{
return m_currentFxParams.resourceMeta.hasNativeEditorSupport;
return muse::audio::hasNativeEditorSupport(m_currentFxParams.resourceMeta);
}
Loading
Loading