Introduced the concept of AudioResourceMeta object and applied it to audio resource resolvers

This commit is contained in:
vpereverzev 2021-08-31 16:49:58 +02:00
parent 29c97df411
commit 27f03de912
24 changed files with 235 additions and 127 deletions

View file

@ -25,6 +25,7 @@
#include <variant> #include <variant>
#include <memory> #include <memory>
#include <set>
#include <string> #include <string>
#include "midi/miditypes.h" #include "midi/miditypes.h"
@ -53,31 +54,87 @@ using MixerChannelId = int32_t;
using AudioSourceName = std::string; using AudioSourceName = std::string;
using AudioResourceId = std::string; using AudioResourceId = std::string;
using AudioResourceIdList = std::vector<AudioResourceId>; using AudioResourceIdList = std::vector<AudioResourceId>;
using AudioResourceVendor = std::string;
enum class AudioResourceType {
Undefined = -1,
FluidSoundfont,
VstPlugin
};
struct AudioResourceMeta {
AudioResourceId id;
AudioResourceType type = AudioResourceType::Undefined;
AudioResourceVendor vendor;
bool hasNativeEditorSupport = false;
bool isValid() const
{
return !id.empty() && !vendor.empty();
}
bool operator==(const AudioResourceMeta& other) const
{
return id == other.id
&& vendor == other.vendor
&& hasNativeEditorSupport == other.hasNativeEditorSupport;
}
};
using AudioResourceMetaList = std::vector<AudioResourceMeta>;
using FxProcessorId = std::string; using FxProcessorId = std::string;
using FxProcessorIdList = std::vector<FxProcessorId>; using FxProcessorIdList = std::vector<FxProcessorId>;
enum class AudioFxType { enum class AudioFxType {
Undefined = -1, Undefined = -1,
Vst VstFx
}; };
enum class AudioFxCategory {
Undefined = -1,
FxEqualizer,
FxAnalyzer,
FxDelay,
FxDistortion,
FxDynamics,
FxFilter,
FxGenerator,
FxMastering,
FxModulation,
FxPitchShift,
FxRestoration,
FxReverb,
FxSurround,
FxTools
};
using AudioFxCategories = std::set<AudioFxCategory>;
struct AudioFxParams { struct AudioFxParams {
AudioFxType type = AudioFxType::Undefined; AudioFxType type() const
AudioResourceId resourceId; {
switch (resourceMeta.type) {
case AudioResourceType::VstPlugin: return AudioFxType::VstFx;
default: return AudioFxType::Undefined;
}
}
AudioFxCategories categories;
AudioResourceMeta resourceMeta;
bool active = false; bool active = false;
bool operator ==(const AudioFxParams& other) const bool operator ==(const AudioFxParams& other) const
{ {
return type == other.type return resourceMeta == other.resourceMeta
&& resourceId == other.resourceId && active == other.active
&& active == other.active; && categories == other.categories;
} }
bool isValid() const bool isValid() const
{ {
return type != AudioFxType::Undefined return resourceMeta.isValid();
&& !resourceId.empty();
} }
}; };
@ -105,19 +162,27 @@ enum class AudioSourceType {
}; };
struct AudioSourceParams { struct AudioSourceParams {
AudioSourceType type = AudioSourceType::Undefined; AudioSourceType type() const
AudioResourceId resourceId; {
switch (resourceMeta.type) {
case AudioResourceType::FluidSoundfont: return AudioSourceType::Fluid;
case AudioResourceType::VstPlugin: return AudioSourceType::Vsti;
default: return AudioSourceType::Undefined;
}
}
AudioResourceMeta resourceMeta;
bool isValid() const bool isValid() const
{ {
return type != AudioSourceType::Undefined return type() != AudioSourceType::Undefined
&& !resourceId.empty(); && resourceMeta.isValid();
} }
bool operator ==(const AudioSourceParams& other) const bool operator ==(const AudioSourceParams& other) const
{ {
return type == other.type return type() == other.type()
&& resourceId == other.resourceId; && resourceMeta == other.resourceMeta;
} }
}; };

View file

@ -44,7 +44,7 @@ public:
virtual void setMasterOutputParams(const AudioOutputParams& params) = 0; virtual void setMasterOutputParams(const AudioOutputParams& params) = 0;
virtual async::Channel<AudioOutputParams> masterOutputParamsChanged() const = 0; virtual async::Channel<AudioOutputParams> masterOutputParamsChanged() const = 0;
virtual async::Promise<AudioResourceIdList> availableOutputResources(const AudioFxType type) const = 0; virtual async::Promise<AudioResourceMetaList> availableOutputResources() const = 0;
virtual async::Promise<AudioSignalChanges> signalChanges(const TrackSequenceId sequenceId, const TrackId trackId) const = 0; virtual async::Promise<AudioSignalChanges> signalChanges(const TrackSequenceId sequenceId, const TrackId trackId) const = 0;
virtual async::Promise<AudioSignalChanges> masterSignalChanges() const = 0; virtual async::Promise<AudioSignalChanges> masterSignalChanges() const = 0;

View file

@ -46,14 +46,14 @@ public:
virtual std::vector<IFxProcessorPtr> resolveFxList(const audio::TrackId trackId, const std::vector<AudioFxParams>& fxParams) = 0; virtual std::vector<IFxProcessorPtr> resolveFxList(const audio::TrackId trackId, const std::vector<AudioFxParams>& fxParams) = 0;
virtual std::vector<IFxProcessorPtr> resolveMasterFxList(const std::vector<AudioFxParams>& fxParams) = 0; virtual std::vector<IFxProcessorPtr> resolveMasterFxList(const std::vector<AudioFxParams>& fxParams) = 0;
virtual AudioResourceIdList resolveResources() const = 0; virtual AudioResourceMetaList resolveResources() const = 0;
virtual void refresh() = 0; virtual void refresh() = 0;
}; };
using IResolverPtr = std::shared_ptr<IResolver>; using IResolverPtr = std::shared_ptr<IResolver>;
virtual std::vector<IFxProcessorPtr> resolveMasterFxList(const AudioFxParamsMap& params) = 0; virtual std::vector<IFxProcessorPtr> resolveMasterFxList(const AudioFxParamsMap& params) = 0;
virtual std::vector<IFxProcessorPtr> resolveFxList(const TrackId trackId, const AudioFxParamsMap& params) = 0; virtual std::vector<IFxProcessorPtr> resolveFxList(const TrackId trackId, const AudioFxParamsMap& params) = 0;
virtual AudioResourceIdList resolveAvailableResources(const AudioFxType type) const = 0; virtual AudioResourceMetaList resolveAvailableResources() const = 0;
virtual void registerResolver(const AudioFxType type, IResolverPtr resolver) = 0; virtual void registerResolver(const AudioFxType type, IResolverPtr resolver) = 0;
}; };

View file

@ -47,6 +47,7 @@ static const Settings::Key USER_SOUNDFONTS_PATH("midi", "application/paths/mySou
static const Settings::Key SHOW_CONTROLS_IN_MIXER("midi", "io/midi/showControlsInMixer"); static const Settings::Key SHOW_CONTROLS_IN_MIXER("midi", "io/midi/showControlsInMixer");
static const AudioResourceId DEFAULT_SOUND_FONT_NAME = "MuseScore_General"; // "GeneralUser GS v1.471.sf2"; // "MuseScore_General.sf3"; static const AudioResourceId DEFAULT_SOUND_FONT_NAME = "MuseScore_General"; // "GeneralUser GS v1.471.sf2"; // "MuseScore_General.sf3";
static const AudioResourceMeta DEFAULT_AUDIO_RESOURCE_META = { DEFAULT_SOUND_FONT_NAME, AudioResourceType::FluidSoundfont, "Fluid", false /*hasNativeEditor*/};
void AudioConfiguration::init() void AudioConfiguration::init()
{ {
@ -124,7 +125,7 @@ void AudioConfiguration::setIsShowControlsInMixer(bool show)
AudioInputParams AudioConfiguration::defaultAudioInputParams() const AudioInputParams AudioConfiguration::defaultAudioInputParams() const
{ {
return { AudioSourceType::Fluid, DEFAULT_SOUND_FONT_NAME }; return { DEFAULT_AUDIO_RESOURCE_META };
} }
const SynthesizerState& AudioConfiguration::defaultSynthesizerState() const const SynthesizerState& AudioConfiguration::defaultSynthesizerState() const

View file

@ -80,7 +80,7 @@ std::vector<IFxProcessorPtr> FxResolver::resolveFxList(const TrackId trackId, co
return result; return result;
} }
AudioResourceIdList FxResolver::resolveAvailableResources(const AudioFxType type) const AudioResourceMetaList FxResolver::resolveAvailableResources() const
{ {
ONLY_AUDIO_WORKER_THREAD; ONLY_AUDIO_WORKER_THREAD;
@ -88,13 +88,14 @@ AudioResourceIdList FxResolver::resolveAvailableResources(const AudioFxType type
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
auto search = m_resolvers.find(type); AudioResourceMetaList result;
if (search == m_resolvers.end()) { for (const auto& pair : m_resolvers) {
return {}; const AudioResourceMetaList& resolvedResources = pair.second->resolveResources();
result.insert(result.end(), resolvedResources.begin(), resolvedResources.end());
} }
return search->second->resolveResources(); return result;
} }
void FxResolver::registerResolver(const AudioFxType type, IResolverPtr resolver) void FxResolver::registerResolver(const AudioFxType type, IResolverPtr resolver)

View file

@ -34,7 +34,7 @@ class FxResolver : public IFxResolver
public: public:
std::vector<IFxProcessorPtr> resolveMasterFxList(const AudioFxParamsMap& fxParams) override; std::vector<IFxProcessorPtr> resolveMasterFxList(const AudioFxParamsMap& fxParams) override;
std::vector<IFxProcessorPtr> resolveFxList(const TrackId trackId, const AudioFxParamsMap& fxParams) override; std::vector<IFxProcessorPtr> resolveFxList(const TrackId trackId, const AudioFxParamsMap& fxParams) override;
AudioResourceIdList resolveAvailableResources(const AudioFxType type) const override; AudioResourceMetaList resolveAvailableResources() const override;
void registerResolver(const AudioFxType type, IResolverPtr resolver) override; void registerResolver(const AudioFxType type, IResolverPtr resolver) override;
private: private:

View file

@ -35,6 +35,8 @@ static const std::map<SoundFontFormat, std::string> FLUID_SF_FILE_EXTENSIONS =
{ SoundFontFormat::SF3, "*.sf3" } { SoundFontFormat::SF3, "*.sf3" }
}; };
static const AudioResourceVendor FLUID_VENDOR_NAME = "Fluid";
FluidResolver::FluidResolver(const io::paths& soundFontDirs, async::Channel<io::paths> sfDirsChanges) FluidResolver::FluidResolver(const io::paths& soundFontDirs, async::Channel<io::paths> sfDirsChanges)
{ {
ONLY_AUDIO_WORKER_THREAD; ONLY_AUDIO_WORKER_THREAD;
@ -67,14 +69,21 @@ ISynthesizerPtr FluidResolver::resolveSynth(const TrackId /*trackId*/, const Aud
return synth; return synth;
} }
AudioResourceIdList FluidResolver::resolveResources() const AudioResourceMetaList FluidResolver::resolveResources() const
{ {
ONLY_AUDIO_WORKER_THREAD; ONLY_AUDIO_WORKER_THREAD;
AudioResourceIdList result(m_resourcesCache.size()); AudioResourceMetaList result;
result.reserve(m_resourcesCache.size());
for (const auto& pair : m_resourcesCache) { for (const auto& pair : m_resourcesCache) {
result.push_back(pair.first); AudioResourceMeta meta;
meta.id = pair.first;
meta.type = AudioResourceType::FluidSoundfont;
meta.vendor = FLUID_VENDOR_NAME;
meta.hasNativeEditorSupport = false;
result.push_back(std::move(meta));
} }
return result; return result;

View file

@ -41,7 +41,7 @@ public:
explicit FluidResolver(const io::paths& soundFontDirs, async::Channel<io::paths> sfDirsChanges); explicit FluidResolver(const io::paths& soundFontDirs, async::Channel<io::paths> sfDirsChanges);
ISynthesizerPtr resolveSynth(const audio::TrackId trackId, const audio::AudioResourceId& resourceId) const override; ISynthesizerPtr resolveSynth(const audio::TrackId trackId, const audio::AudioResourceId& resourceId) const override;
AudioResourceIdList resolveResources() const override; audio::AudioResourceMetaList resolveResources() const override;
void refresh() override; void refresh() override;

View file

@ -57,14 +57,14 @@ ISynthesizerPtr SynthResolver::resolveSynth(const TrackId trackId, const AudioIn
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
auto search = m_resolvers.find(params.type); auto search = m_resolvers.find(params.type());
if (search == m_resolvers.end()) { if (search == m_resolvers.end()) {
return nullptr; return nullptr;
} }
const IResolverPtr& resolver = search->second; const IResolverPtr& resolver = search->second;
return resolver->resolveSynth(trackId, params.resourceId); return resolver->resolveSynth(trackId, params.resourceMeta.id);
} }
ISynthesizerPtr SynthResolver::resolveDefaultSynth(const TrackId trackId) const ISynthesizerPtr SynthResolver::resolveDefaultSynth(const TrackId trackId) const
@ -74,7 +74,7 @@ ISynthesizerPtr SynthResolver::resolveDefaultSynth(const TrackId trackId) const
return resolveSynth(trackId, m_defaultInputParams); return resolveSynth(trackId, m_defaultInputParams);
} }
AudioResourceIdList SynthResolver::resolveAvailableResources(const AudioSourceType type) const AudioResourceMetaList SynthResolver::resolveAvailableResources() const
{ {
ONLY_AUDIO_WORKER_THREAD; ONLY_AUDIO_WORKER_THREAD;
@ -82,14 +82,14 @@ AudioResourceIdList SynthResolver::resolveAvailableResources(const AudioSourceTy
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
auto search = m_resolvers.find(type); AudioResourceMetaList result;
if (search != m_resolvers.end()) { for (const auto& pair : m_resolvers) {
return search->second->resolveResources(); const AudioResourceMetaList& resolvedResources = pair.second->resolveResources();
result.insert(result.end(), resolvedResources.begin(), resolvedResources.end());
} }
LOGE() << "Unable to find a resolver for type: " << static_cast<int>(type); return result;
return {};
} }
void SynthResolver::registerResolver(const AudioSourceType type, IResolverPtr resolver) void SynthResolver::registerResolver(const AudioSourceType type, IResolverPtr resolver)

View file

@ -37,7 +37,7 @@ public:
ISynthesizerPtr resolveSynth(const TrackId trackId, const AudioInputParams& params) const override; ISynthesizerPtr resolveSynth(const TrackId trackId, const AudioInputParams& params) const override;
ISynthesizerPtr resolveDefaultSynth(const TrackId trackId) const override; ISynthesizerPtr resolveDefaultSynth(const TrackId trackId) const override;
AudioResourceIdList resolveAvailableResources(const AudioSourceType type) const override; AudioResourceMetaList resolveAvailableResources() const override;
void registerResolver(const AudioSourceType type, IResolverPtr resolver) override; void registerResolver(const AudioSourceType type, IResolverPtr resolver) override;

View file

@ -119,17 +119,13 @@ Channel<AudioOutputParams> AudioOutputHandler::masterOutputParamsChanged() const
return m_masterOutputParamsChanged; return m_masterOutputParamsChanged;
} }
Promise<AudioResourceIdList> AudioOutputHandler::availableOutputResources(const AudioFxType type) const Promise<AudioResourceMetaList> AudioOutputHandler::availableOutputResources() const
{ {
return Promise<AudioResourceIdList>([this, type](Promise<AudioResourceIdList>::Resolve resolve, return Promise<AudioResourceMetaList>([this](Promise<AudioResourceMetaList>::Resolve resolve,
Promise<AudioResourceIdList>::Reject reject) { Promise<AudioResourceMetaList>::Reject /*reject*/) {
ONLY_AUDIO_WORKER_THREAD; ONLY_AUDIO_WORKER_THREAD;
if (type == AudioFxType::Undefined) { resolve(fxResolver()->resolveAvailableResources());
reject(static_cast<int>(Err::InvalidFxParams), "unable to get resources for undefined fx type");
}
resolve(fxResolver()->resolveAvailableResources(type));
}, AudioThread::ID); }, AudioThread::ID);
} }
@ -143,6 +139,7 @@ Promise<AudioSignalChanges> AudioOutputHandler::signalChanges(const TrackSequenc
if (!s) { if (!s) {
reject(static_cast<int>(Err::InvalidSequenceId), "invalid sequence id"); reject(static_cast<int>(Err::InvalidSequenceId), "invalid sequence id");
return;
} }
resolve({ s->audioIO()->signalAmplitudeChanged(trackId), s->audioIO()->volumePressureChanged(trackId) }); resolve({ s->audioIO()->signalAmplitudeChanged(trackId), s->audioIO()->volumePressureChanged(trackId) });

View file

@ -47,7 +47,7 @@ public:
void setMasterOutputParams(const AudioOutputParams& params) override; void setMasterOutputParams(const AudioOutputParams& params) override;
async::Channel<AudioOutputParams> masterOutputParamsChanged() const override; async::Channel<AudioOutputParams> masterOutputParamsChanged() const override;
async::Promise<AudioResourceIdList> availableOutputResources(const AudioFxType type) const override; async::Promise<AudioResourceMetaList> availableOutputResources() const override;
async::Promise<AudioSignalChanges> signalChanges(const TrackSequenceId sequenceId, const TrackId trackId) const override; async::Promise<AudioSignalChanges> signalChanges(const TrackSequenceId sequenceId, const TrackId trackId) const override;
async::Promise<AudioSignalChanges> masterSignalChanges() const override; async::Promise<AudioSignalChanges> masterSignalChanges() const override;

View file

@ -150,17 +150,13 @@ Channel<TrackSequenceId, TrackId> TracksHandler::trackRemoved() const
return m_trackRemoved; return m_trackRemoved;
} }
Promise<AudioResourceIdList> TracksHandler::availableInputResources(const AudioSourceType type) const Promise<AudioResourceMetaList> TracksHandler::availableInputResources() const
{ {
return Promise<AudioResourceIdList>([this, type](Promise<AudioResourceIdList>::Resolve resolve, return Promise<AudioResourceMetaList>([this](Promise<AudioResourceMetaList>::Resolve resolve,
Promise<AudioResourceIdList>::Reject reject) { Promise<AudioResourceMetaList>::Reject /*reject*/) {
ONLY_AUDIO_WORKER_THREAD; ONLY_AUDIO_WORKER_THREAD;
if (type == AudioSourceType::Undefined) { resolve(resolver()->resolveAvailableResources());
reject(static_cast<int>(Err::InvalidAudioSourceParams), "unable to get resources for undefined audio source type");
}
resolve(resolver()->resolveAvailableResources(type));
}, AudioThread::ID); }, AudioThread::ID);
} }

View file

@ -39,6 +39,7 @@ public:
~TracksHandler(); ~TracksHandler();
async::Promise<TrackIdList> trackIdList(const TrackSequenceId sequenceId) const override; async::Promise<TrackIdList> trackIdList(const TrackSequenceId sequenceId) const override;
async::Promise<TrackName> trackName(const TrackSequenceId sequenceId, const TrackId trackId) const override;
async::Promise<TrackId> addTrack(const TrackSequenceId sequenceId, const std::string& trackName, midi::MidiData&& playbackData, async::Promise<TrackId> addTrack(const TrackSequenceId sequenceId, const std::string& trackName, midi::MidiData&& playbackData,
AudioParams&& params) override; AudioParams&& params) override;
async::Promise<TrackId> addTrack(const TrackSequenceId sequenceId, const std::string& trackName, io::Device* playbackData, async::Promise<TrackId> addTrack(const TrackSequenceId sequenceId, const std::string& trackName, io::Device* playbackData,
@ -49,7 +50,7 @@ public:
async::Channel<TrackSequenceId, TrackId> trackAdded() const override; async::Channel<TrackSequenceId, TrackId> trackAdded() const override;
async::Channel<TrackSequenceId, TrackId> trackRemoved() const override; async::Channel<TrackSequenceId, TrackId> trackRemoved() const override;
async::Promise<AudioResourceIdList> availableInputResources(const AudioSourceType type) const override; async::Promise<AudioResourceMetaList> availableInputResources() const override;
async::Promise<AudioInputParams> inputParams(const TrackSequenceId sequenceId, const TrackId trackId) const override; async::Promise<AudioInputParams> inputParams(const TrackSequenceId sequenceId, const TrackId trackId) const override;
void setInputParams(const TrackSequenceId sequenceId, const TrackId trackId, const AudioInputParams& params) override; void setInputParams(const TrackSequenceId sequenceId, const TrackId trackId, const AudioInputParams& params) override;

View file

@ -49,12 +49,16 @@ void VstPluginListModelExample::load()
<< "error text: " << text; << "error text: " << text;
}); });
playback()->tracks()->availableInputResources(audio::AudioSourceType::Vsti) playback()->tracks()->availableInputResources()
.onResolve(this, [this](AudioResourceIdList idList) { .onResolve(this, [this](AudioResourceMetaList resourceList) {
QVariantList list; QVariantList list;
for (const AudioResourceId& id : idList) { for (const auto& meta : resourceList) {
QVariantMap item = { { "value", QString::fromStdString(id) } }; if (meta.type != AudioResourceType::VstPlugin) {
continue;
}
QVariantMap item = { { "value", QString::fromStdString(meta.id) } };
list << item; list << item;
} }
setAvailableSynthResources(list); setAvailableSynthResources(list);
@ -65,12 +69,12 @@ void VstPluginListModelExample::load()
<< "error text: " << text; << "error text: " << text;
}); });
playback()->audioOutput()->availableOutputResources(audio::AudioFxType::Vst) playback()->audioOutput()->availableOutputResources()
.onResolve(this, [this](AudioResourceIdList idList) { .onResolve(this, [this](AudioResourceMetaList resources) {
QVariantList list; QVariantList list;
for (const AudioResourceId& id : idList) { for (const auto& meta : resources) {
QVariantMap item = { { "value", QString::fromStdString(id) } }; QVariantMap item = { { "value", QString::fromStdString(meta.id) } };
list << item; list << item;
} }
setAvailableFxResources(list); setAvailableFxResources(list);
@ -209,8 +213,7 @@ const QString& VstPluginListModelExample::currentSynthResource() const
void VstPluginListModelExample::applyNewInputParams() void VstPluginListModelExample::applyNewInputParams()
{ {
AudioInputParams inputParams; AudioInputParams inputParams;
inputParams.type = AudioSourceType::Vsti; inputParams.resourceMeta.id = m_currentSynthResource.toStdString();
inputParams.resourceId = m_currentSynthResource.toStdString();
playback()->tracks()->setInputParams(m_currentSequenceId, m_currentTrackId, inputParams); playback()->tracks()->setInputParams(m_currentSequenceId, m_currentTrackId, inputParams);
} }
@ -218,11 +221,10 @@ void VstPluginListModelExample::applyNewInputParams()
void VstPluginListModelExample::applyNewOutputParams() void VstPluginListModelExample::applyNewOutputParams()
{ {
AudioFxParams fxParams; AudioFxParams fxParams;
fxParams.type = AudioFxType::Vst; fxParams.resourceMeta.id = m_currentFxResource.toStdString();
fxParams.resourceId = m_currentFxResource.toStdString();
AudioOutputParams outputParams; AudioOutputParams outputParams;
outputParams.fxParams.emplace(AudioFxType::Vst, std::vector<AudioFxParams>({ fxParams })); outputParams.fxParams.emplace(AudioFxType::VstFx, std::vector<AudioFxParams>({ fxParams }));
playback()->audioOutput()->setOutputParams(m_currentSequenceId, m_currentTrackId, outputParams); playback()->audioOutput()->setOutputParams(m_currentSequenceId, m_currentTrackId, outputParams);
} }

View file

@ -33,12 +33,12 @@ VstFxProcessor::VstFxProcessor(VstPluginPtr&& pluginPtr)
void VstFxProcessor::init() void VstFxProcessor::init()
{ {
m_vstAudioClient->init(m_pluginPtr); m_vstAudioClient->init(VstPluginType::Fx, m_pluginPtr);
} }
AudioFxType VstFxProcessor::type() const AudioFxType VstFxProcessor::type() const
{ {
return audio::AudioFxType::Vst; return audio::AudioFxType::VstFx;
} }
void VstFxProcessor::setSampleRate(unsigned int sampleRate) void VstFxProcessor::setSampleRate(unsigned int sampleRate)

View file

@ -35,18 +35,12 @@ std::vector<IFxProcessorPtr> VstFxResolver::resolveFxList(const audio::TrackId t
return {}; return {};
} }
AudioResourceIdList newResourcesidList;
for (const auto& param : fxParams) {
newResourcesidList.emplace_back(param.resourceId);
}
FxMap& fxMap = m_tracksFxMap[trackId]; FxMap& fxMap = m_tracksFxMap[trackId];
updateTrackFxMap(fxMap, trackId, newResourcesidList); updateTrackFxMap(fxMap, trackId, fxParams);
std::vector<IFxProcessorPtr> result; std::vector<IFxProcessorPtr> result;
for (const auto& pair : m_masterFxMap) { for (const auto& pair : fxMap) {
result.emplace_back(pair.second); result.emplace_back(pair.second);
} }
@ -60,13 +54,7 @@ std::vector<IFxProcessorPtr> VstFxResolver::resolveMasterFxList(const std::vecto
return {}; return {};
} }
AudioResourceIdList newResourcesidList; updateMasterFxMap(fxParams);
for (const auto& param : fxParams) {
newResourcesidList.emplace_back(param.resourceId);
}
updateMasterFxMap(newResourcesidList);
std::vector<IFxProcessorPtr> result; std::vector<IFxProcessorPtr> result;
@ -77,9 +65,9 @@ std::vector<IFxProcessorPtr> VstFxResolver::resolveMasterFxList(const std::vecto
return result; return result;
} }
AudioResourceIdList VstFxResolver::resolveResources() const AudioResourceMetaList VstFxResolver::resolveResources() const
{ {
return pluginModulesRepo()->moduleIdList(VstPluginType::Fx); return pluginModulesRepo()->fxModulesMeta();
} }
void VstFxResolver::refresh() void VstFxResolver::refresh()
@ -121,15 +109,20 @@ VstFxPtr VstFxResolver::createTrackFx(const audio::TrackId trackId, const audio:
return fx; return fx;
} }
void VstFxResolver::updateTrackFxMap(FxMap& fxMap, const audio::TrackId trackId, const audio::AudioResourceIdList& newResourceIdList) void VstFxResolver::updateTrackFxMap(FxMap& fxMap, const audio::TrackId trackId, const std::vector<AudioFxParams>& fxParams)
{ {
AudioResourceIdList currentResourceIdList; AudioResourceIdList currentResourceIdList;
for (const auto& pair : fxMap) { for (const auto& pair : fxMap) {
currentResourceIdList.emplace_back(pair.first); currentResourceIdList.emplace_back(pair.first);
} }
AudioResourceIdList newResourcesidList;
for (const auto& param : fxParams) {
newResourcesidList.emplace_back(param.resourceMeta.id);
}
audio::AudioResourceIdList idListToRemove; audio::AudioResourceIdList idListToRemove;
fxListToRemove(newResourceIdList, currentResourceIdList, idListToRemove); fxListToRemove(newResourcesidList, currentResourceIdList, idListToRemove);
for (const auto& idToRemove : idListToRemove) { for (const auto& idToRemove : idListToRemove) {
pluginsRegister()->unregisterFxPlugin(trackId, idToRemove); pluginsRegister()->unregisterFxPlugin(trackId, idToRemove);
@ -137,22 +130,32 @@ void VstFxResolver::updateTrackFxMap(FxMap& fxMap, const audio::TrackId trackId,
} }
audio::AudioResourceIdList idListToCreate; audio::AudioResourceIdList idListToCreate;
fxListToCreate(newResourceIdList, currentResourceIdList, idListToCreate); fxListToCreate(newResourcesidList, currentResourceIdList, idListToCreate);
for (const auto& idToCreate : idListToCreate) { for (const auto& idToCreate : idListToCreate) {
fxMap.emplace(idToCreate, createTrackFx(trackId, idToCreate)); fxMap.emplace(idToCreate, createTrackFx(trackId, idToCreate));
} }
for (const auto& param : fxParams) {
VstFxPtr& fxPtr = fxMap[param.resourceMeta.id];
fxPtr->setActive(param.active);
}
} }
void VstFxResolver::updateMasterFxMap(const audio::AudioResourceIdList& newResourceIdList) void VstFxResolver::updateMasterFxMap(const std::vector<AudioFxParams>& fxParams)
{ {
AudioResourceIdList currentResourceIdList; AudioResourceIdList currentResourceIdList;
for (const auto& pair : m_masterFxMap) { for (const auto& pair : m_masterFxMap) {
currentResourceIdList.emplace_back(pair.first); currentResourceIdList.emplace_back(pair.first);
} }
AudioResourceIdList newResourcesidList;
for (const auto& param : fxParams) {
newResourcesidList.emplace_back(param.resourceMeta.id);
}
audio::AudioResourceIdList idListToRemove; audio::AudioResourceIdList idListToRemove;
fxListToRemove(newResourceIdList, currentResourceIdList, idListToRemove); fxListToRemove(newResourcesidList, currentResourceIdList, idListToRemove);
for (const auto& idToRemove : idListToRemove) { for (const auto& idToRemove : idListToRemove) {
pluginsRegister()->unregisterMasterFxPlugin(idToRemove); pluginsRegister()->unregisterMasterFxPlugin(idToRemove);
@ -160,11 +163,16 @@ void VstFxResolver::updateMasterFxMap(const audio::AudioResourceIdList& newResou
} }
audio::AudioResourceIdList idListToCreate; audio::AudioResourceIdList idListToCreate;
fxListToCreate(newResourceIdList, currentResourceIdList, idListToCreate); fxListToCreate(newResourcesidList, currentResourceIdList, idListToCreate);
for (const auto& idToCreate : idListToCreate) { for (const auto& idToCreate : idListToCreate) {
m_masterFxMap.emplace(idToCreate, createMasterFx(idToCreate)); m_masterFxMap.emplace(idToCreate, createMasterFx(idToCreate));
} }
for (const auto& param : fxParams) {
VstFxPtr& fxPtr = m_masterFxMap[param.resourceMeta.id];
fxPtr->setActive(param.active);
}
} }
void VstFxResolver::fxListToRemove(const AudioResourceIdList& currentResourceIdList, void VstFxResolver::fxListToRemove(const AudioResourceIdList& currentResourceIdList,

View file

@ -47,7 +47,7 @@ public:
std::vector<audio::IFxProcessorPtr> resolveFxList(const audio::TrackId trackId, std::vector<audio::IFxProcessorPtr> resolveFxList(const audio::TrackId trackId,
const std::vector<audio::AudioFxParams>& fxParams) override; const std::vector<audio::AudioFxParams>& fxParams) override;
std::vector<audio::IFxProcessorPtr> resolveMasterFxList(const std::vector<audio::AudioFxParams>& fxParams) override; std::vector<audio::IFxProcessorPtr> resolveMasterFxList(const std::vector<audio::AudioFxParams>& fxParams) override;
audio::AudioResourceIdList resolveResources() const override; audio::AudioResourceMetaList resolveResources() const override;
void refresh() override; void refresh() override;
private: private:
@ -56,8 +56,8 @@ private:
VstFxPtr createMasterFx(const audio::AudioResourceId& resourceId) const; VstFxPtr createMasterFx(const audio::AudioResourceId& resourceId) const;
VstFxPtr createTrackFx(const audio::TrackId trackId, const audio::AudioResourceId& resourceId) const; VstFxPtr createTrackFx(const audio::TrackId trackId, const audio::AudioResourceId& resourceId) const;
void updateMasterFxMap(const audio::AudioResourceIdList& newResourceIdList); void updateMasterFxMap(const std::vector<audio::AudioFxParams>& fxParams);
void updateTrackFxMap(FxMap& fxMap, const audio::TrackId trackId, const audio::AudioResourceIdList& newResourceIdList); void updateTrackFxMap(FxMap& fxMap, const audio::TrackId trackId, const std::vector<audio::AudioFxParams>& fxParams);
void fxListToRemove(const audio::AudioResourceIdList& currentResourceIdList, const audio::AudioResourceIdList& newResourceIdList, void fxListToRemove(const audio::AudioResourceIdList& currentResourceIdList, const audio::AudioResourceIdList& newResourceIdList,
audio::AudioResourceIdList& resultList); audio::AudioResourceIdList& resultList);

View file

@ -67,7 +67,7 @@ VstSynthPtr VstiResolver::createSynth(const audio::TrackId trackId, const audio:
return synth; return synth;
} }
AudioResourceIdList VstiResolver::resolveResources() const AudioResourceMetaList VstiResolver::resolveResources() const
{ {
return pluginModulesRepo()->moduleIdList(VstPluginType::Instrument); return pluginModulesRepo()->instrumentModulesMeta();
} }

View file

@ -39,7 +39,7 @@ class VstiResolver : public audio::synth::ISynthResolver::IResolver
INJECT(vst, IVstPluginsRegister, pluginsRegister) INJECT(vst, IVstPluginsRegister, pluginsRegister)
public: public:
audio::synth::ISynthesizerPtr resolveSynth(const audio::TrackId trackId, const audio::AudioResourceId& resourceId) const override; audio::synth::ISynthesizerPtr resolveSynth(const audio::TrackId trackId, const audio::AudioResourceId& resourceId) const override;
audio::AudioResourceIdList resolveResources() const override; audio::AudioResourceMetaList resolveResources() const override;
void refresh() override; void refresh() override;
private: private:

View file

@ -65,36 +65,22 @@ PluginModulePtr VstModulesRepository::pluginModule(const audio::AudioResourceId&
return nullptr; return nullptr;
} }
audio::AudioResourceIdList VstModulesRepository::moduleIdList(const VstPluginType& type) const audio::AudioResourceMetaList VstModulesRepository::instrumentModulesMeta() const
{ {
ONLY_AUDIO_THREAD(threadSecurer); ONLY_AUDIO_THREAD(threadSecurer);
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
audio::AudioResourceIdList result; return modulesMetaList(VstPluginType::Instrument);
}
if (type == VstPluginType::Undefined) { audio::AudioResourceMetaList VstModulesRepository::fxModulesMeta() const
return result; {
} ONLY_AUDIO_THREAD(threadSecurer);
for (const auto& pair : m_modules) { std::lock_guard lock(m_mutex);
PluginModulePtr module = pair.second;
const auto& factory = module->getFactory(); return modulesMetaList(VstPluginType::Fx);
for (auto& classInfo : factory.classInfos()) {
if (classInfo.category() != kVstAudioEffectClass) {
continue;
}
std::string subCategoriesStr = classInfo.subCategoriesString();
if (subCategoriesStr.find(PLUGIN_TYPE_MAP.at(type)) != std::string::npos) {
result.emplace_back(pair.first);
}
}
}
return result;
} }
void VstModulesRepository::refresh() void VstModulesRepository::refresh()
@ -128,6 +114,45 @@ void VstModulesRepository::addModule(const io::path& path)
m_modules.emplace(io::basename(path).toStdString(), module); m_modules.emplace(io::basename(path).toStdString(), module);
} }
audio::AudioResourceMetaList VstModulesRepository::modulesMetaList(const VstPluginType& type) const
{
audio::AudioResourceMetaList result;
static auto hasNativeEditorSupport = []() {
#ifdef Q_OS_LINUX
//!Note Host applications on Linux should provide their own event loop via VST3 API,
//! otherwise it'll be impossible to launch native VST editor views
return false;
#else
return true;
#endif
};
for (const auto& pair : m_modules) {
PluginModulePtr module = pair.second;
const auto& factory = module->getFactory();
for (auto& classInfo : factory.classInfos()) {
if (classInfo.category() != kVstAudioEffectClass) {
continue;
}
std::string subCategoriesStr = classInfo.subCategoriesString();
if (subCategoriesStr.find(PLUGIN_TYPE_MAP.at(type)) != std::string::npos) {
audio::AudioResourceMeta meta;
meta.id = pair.first;
meta.type = audio::AudioResourceType::VstPlugin;
meta.vendor = factory.info().vendor();
meta.hasNativeEditorSupport = hasNativeEditorSupport();
result.emplace_back(std::move(meta));
break;
}
}
}
return result;
}
RetVal<io::paths> VstModulesRepository::pluginPathsFromCustomLocation(const io::path& customPath) const RetVal<io::paths> VstModulesRepository::pluginPathsFromCustomLocation(const io::path& customPath) const
{ {
RetVal<io::paths> pluginPaths = fileSystem()->scanFiles(customPath, QStringList(QString::fromStdString(VST3_PACKAGE_EXTENSION))); RetVal<io::paths> pluginPaths = fileSystem()->scanFiles(customPath, QStringList(QString::fromStdString(VST3_PACKAGE_EXTENSION)));

View file

@ -48,11 +48,14 @@ public:
void init(); void init();
PluginModulePtr pluginModule(const audio::AudioResourceId& resourceId) const override; PluginModulePtr pluginModule(const audio::AudioResourceId& resourceId) const override;
audio::AudioResourceIdList moduleIdList(const VstPluginType& type) const override;
audio::AudioResourceMetaList instrumentModulesMeta() const override;
audio::AudioResourceMetaList fxModulesMeta() const override;
void refresh() override; void refresh() override;
private: private:
void addModule(const io::path& path); void addModule(const io::path& path);
audio::AudioResourceMetaList modulesMetaList(const VstPluginType& type) const;
RetVal<io::paths> pluginPathsFromCustomLocation(const io::path& customPath) const; RetVal<io::paths> pluginPathsFromCustomLocation(const io::path& customPath) const;
PluginModule::PathList pluginPathsFromDefaultLocation() const; PluginModule::PathList pluginPathsFromDefaultLocation() const;

View file

@ -37,7 +37,8 @@ public:
virtual ~IVstModulesRepository() = default; virtual ~IVstModulesRepository() = default;
virtual PluginModulePtr pluginModule(const audio::AudioResourceId& resourceId) const = 0; virtual PluginModulePtr pluginModule(const audio::AudioResourceId& resourceId) const = 0;
virtual audio::AudioResourceIdList moduleIdList(const VstPluginType& type) const = 0; virtual audio::AudioResourceMetaList instrumentModulesMeta() const = 0;
virtual audio::AudioResourceMetaList fxModulesMeta() const = 0;
virtual void refresh() = 0; virtual void refresh() = 0;
}; };
} }

View file

@ -74,8 +74,7 @@ void ProjectAudioSettings::makeDefault()
AudioInputParams ProjectAudioSettings::inputParamsFromJson(const QJsonObject& object) const AudioInputParams ProjectAudioSettings::inputParamsFromJson(const QJsonObject& object) const
{ {
AudioInputParams result; AudioInputParams result;
result.type = sourceTypeFromString(object.value("type").toString()); result.resourceMeta.id = object.value("resourceId").toString().toStdString();
result.resourceId = object.value("resourceId").toString().toStdString();
return result; return result;
} }
@ -93,8 +92,8 @@ AudioOutputParams ProjectAudioSettings::outputParamsFromJson(const QJsonObject&
QJsonObject ProjectAudioSettings::inputParamsToJson(const audio::AudioInputParams& params) const QJsonObject ProjectAudioSettings::inputParamsToJson(const audio::AudioInputParams& params) const
{ {
QJsonObject result; QJsonObject result;
result.insert("type", sourceTypeToString(params.type)); result.insert("type", sourceTypeToString(params.type()));
result.insert("resourceId", QString::fromStdString(params.resourceId)); result.insert("resourceId", QString::fromStdString(params.resourceMeta.id));
return result; return result;
} }