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 76 files
+705 −0 LICENSE.txt
+4 −0 framework/CMakeLists.txt
+141 −52 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
+124 −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
+132 −35 framework/audioplugins/internal/knownaudiopluginsregister.cpp
+10 −4 framework/audioplugins/internal/knownaudiopluginsregister.h
+142 −35 framework/audioplugins/internal/registeraudiopluginsscenario.cpp
+5 −5 framework/audioplugins/internal/registeraudiopluginsscenario.h
+13 −7 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
+205 −39 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
+340 −129 framework/audioplugins/tests/registeraudiopluginsscenariotest.cpp
+1 −0 framework/cmake/MuseDeclareOptions.cmake
+1 −0 framework/cmake/MuseModules.cmake
+4 −7 framework/global/CMakeLists.txt
+1 −5 framework/global/serialization/xmlstreamwriter.cpp
+4 −0 framework/global/tests/ringqueue_tests.cpp
+1,887 −0 framework/global/thirdparty/utfcpp/API_REFERENCE.md
+11 −1,937 framework/global/thirdparty/utfcpp/README.md
+1 −1 framework/global/thirdparty/utfcpp/_version
+266 −295 framework/global/thirdparty/utfcpp/utf8/checked.h
+470 −379 framework/global/thirdparty/utfcpp/utf8/core.h
+31 −28 framework/global/thirdparty/utfcpp/utf8/cpp11.h
+53 −49 framework/global/thirdparty/utfcpp/utf8/cpp17.h
+89 −85 framework/global/thirdparty/utfcpp/utf8/cpp20.h
+226 −238 framework/global/thirdparty/utfcpp/utf8/unchecked.h
+1 −5 framework/global/types/string.cpp
+1 −1 framework/musesampler/internal/musesamplerresolver.cpp
+4 −0 framework/musesampler/musesamplertypes.h
+46 −0 framework/rcontrol/CMakeLists.txt
+153 −0 framework/rcontrol/mcp/bridge/main.cpp
+40 −0 framework/rcontrol/mcp/itransport.h
+76 −0 framework/rcontrol/mcp/mcpcontroller.cpp
+50 −0 framework/rcontrol/mcp/mcpcontroller.h
+214 −0 framework/rcontrol/mcp/mcpserver.cpp
+68 −0 framework/rcontrol/mcp/mcpserver.h
+76 −0 framework/rcontrol/mcp/mcptypes.h
+117 −0 framework/rcontrol/mcp/transport/tcptransport.cpp
+64 −0 framework/rcontrol/mcp/transport/tcptransport.h
+56 −0 framework/rcontrol/rcontrolmodule.cpp
+51 −0 framework/rcontrol/rcontrolmodule.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
+19 −5 framework/vst/internal/vstmodulesrepository.cpp
+1 −2 framework/vst/internal/vstmodulesrepository.h
+13 −10 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.
PluginAttributes 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::audio::intAttribute(resourceMeta, u"museUID");

const muse::ByteArray drumMapping = museSampler()->drumMapping(instrumentId);
IF_ASSERT_FAILED(!drumMapping.empty()) {
Expand Down
2 changes: 2 additions & 0 deletions src/playback/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ target_sources(playback PRIVATE
internal/soundprofilesrepository.h
internal/drumsetloader.cpp
internal/drumsetloader.h
internal/audiometabridge.cpp
internal/audiometabridge.h
)

if (MUE_BUILD_PLAYBACK_TESTS)
Expand Down
65 changes: 65 additions & 0 deletions src/playback/internal/audiometabridge.cpp
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.
*/

#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;
}
}
39 changes: 39 additions & 0 deletions src/playback/internal/audiometabridge.h
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.
*/

#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);
}
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::audio::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
Loading
Loading