Introduced the concept of AudioResourceMeta object and applied it to audio resource resolvers
This commit is contained in:
parent
29c97df411
commit
27f03de912
24 changed files with 235 additions and 127 deletions
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <variant>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "midi/miditypes.h"
|
||||
|
@ -53,31 +54,87 @@ using MixerChannelId = int32_t;
|
|||
using AudioSourceName = std::string;
|
||||
using AudioResourceId = std::string;
|
||||
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 FxProcessorIdList = std::vector<FxProcessorId>;
|
||||
|
||||
enum class AudioFxType {
|
||||
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 {
|
||||
AudioFxType type = AudioFxType::Undefined;
|
||||
AudioResourceId resourceId;
|
||||
AudioFxType type() const
|
||||
{
|
||||
switch (resourceMeta.type) {
|
||||
case AudioResourceType::VstPlugin: return AudioFxType::VstFx;
|
||||
default: return AudioFxType::Undefined;
|
||||
}
|
||||
}
|
||||
|
||||
AudioFxCategories categories;
|
||||
AudioResourceMeta resourceMeta;
|
||||
bool active = false;
|
||||
|
||||
bool operator ==(const AudioFxParams& other) const
|
||||
{
|
||||
return type == other.type
|
||||
&& resourceId == other.resourceId
|
||||
&& active == other.active;
|
||||
return resourceMeta == other.resourceMeta
|
||||
&& active == other.active
|
||||
&& categories == other.categories;
|
||||
}
|
||||
|
||||
bool isValid() const
|
||||
{
|
||||
return type != AudioFxType::Undefined
|
||||
&& !resourceId.empty();
|
||||
return resourceMeta.isValid();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -105,19 +162,27 @@ enum class AudioSourceType {
|
|||
};
|
||||
|
||||
struct AudioSourceParams {
|
||||
AudioSourceType type = AudioSourceType::Undefined;
|
||||
AudioResourceId resourceId;
|
||||
AudioSourceType type() const
|
||||
{
|
||||
switch (resourceMeta.type) {
|
||||
case AudioResourceType::FluidSoundfont: return AudioSourceType::Fluid;
|
||||
case AudioResourceType::VstPlugin: return AudioSourceType::Vsti;
|
||||
default: return AudioSourceType::Undefined;
|
||||
}
|
||||
}
|
||||
|
||||
AudioResourceMeta resourceMeta;
|
||||
|
||||
bool isValid() const
|
||||
{
|
||||
return type != AudioSourceType::Undefined
|
||||
&& !resourceId.empty();
|
||||
return type() != AudioSourceType::Undefined
|
||||
&& resourceMeta.isValid();
|
||||
}
|
||||
|
||||
bool operator ==(const AudioSourceParams& other) const
|
||||
{
|
||||
return type == other.type
|
||||
&& resourceId == other.resourceId;
|
||||
return type() == other.type()
|
||||
&& resourceMeta == other.resourceMeta;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
virtual void setMasterOutputParams(const AudioOutputParams& params) = 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> masterSignalChanges() const = 0;
|
||||
|
|
|
@ -46,14 +46,14 @@ public:
|
|||
|
||||
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 AudioResourceIdList resolveResources() const = 0;
|
||||
virtual AudioResourceMetaList resolveResources() const = 0;
|
||||
virtual void refresh() = 0;
|
||||
};
|
||||
using IResolverPtr = std::shared_ptr<IResolver>;
|
||||
|
||||
virtual std::vector<IFxProcessorPtr> resolveMasterFxList(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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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 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()
|
||||
{
|
||||
|
@ -124,7 +125,7 @@ void AudioConfiguration::setIsShowControlsInMixer(bool show)
|
|||
|
||||
AudioInputParams AudioConfiguration::defaultAudioInputParams() const
|
||||
{
|
||||
return { AudioSourceType::Fluid, DEFAULT_SOUND_FONT_NAME };
|
||||
return { DEFAULT_AUDIO_RESOURCE_META };
|
||||
}
|
||||
|
||||
const SynthesizerState& AudioConfiguration::defaultSynthesizerState() const
|
||||
|
|
|
@ -80,7 +80,7 @@ std::vector<IFxProcessorPtr> FxResolver::resolveFxList(const TrackId trackId, co
|
|||
return result;
|
||||
}
|
||||
|
||||
AudioResourceIdList FxResolver::resolveAvailableResources(const AudioFxType type) const
|
||||
AudioResourceMetaList FxResolver::resolveAvailableResources() const
|
||||
{
|
||||
ONLY_AUDIO_WORKER_THREAD;
|
||||
|
||||
|
@ -88,13 +88,14 @@ AudioResourceIdList FxResolver::resolveAvailableResources(const AudioFxType type
|
|||
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
auto search = m_resolvers.find(type);
|
||||
AudioResourceMetaList result;
|
||||
|
||||
if (search == m_resolvers.end()) {
|
||||
return {};
|
||||
for (const auto& pair : m_resolvers) {
|
||||
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)
|
||||
|
|
|
@ -34,7 +34,7 @@ class FxResolver : public IFxResolver
|
|||
public:
|
||||
std::vector<IFxProcessorPtr> resolveMasterFxList(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;
|
||||
|
||||
private:
|
||||
|
|
|
@ -35,6 +35,8 @@ static const std::map<SoundFontFormat, std::string> FLUID_SF_FILE_EXTENSIONS =
|
|||
{ SoundFontFormat::SF3, "*.sf3" }
|
||||
};
|
||||
|
||||
static const AudioResourceVendor FLUID_VENDOR_NAME = "Fluid";
|
||||
|
||||
FluidResolver::FluidResolver(const io::paths& soundFontDirs, async::Channel<io::paths> sfDirsChanges)
|
||||
{
|
||||
ONLY_AUDIO_WORKER_THREAD;
|
||||
|
@ -67,14 +69,21 @@ ISynthesizerPtr FluidResolver::resolveSynth(const TrackId /*trackId*/, const Aud
|
|||
return synth;
|
||||
}
|
||||
|
||||
AudioResourceIdList FluidResolver::resolveResources() const
|
||||
AudioResourceMetaList FluidResolver::resolveResources() const
|
||||
{
|
||||
ONLY_AUDIO_WORKER_THREAD;
|
||||
|
||||
AudioResourceIdList result(m_resourcesCache.size());
|
||||
AudioResourceMetaList result;
|
||||
result.reserve(m_resourcesCache.size());
|
||||
|
||||
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;
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
explicit FluidResolver(const io::paths& soundFontDirs, async::Channel<io::paths> sfDirsChanges);
|
||||
|
||||
ISynthesizerPtr resolveSynth(const audio::TrackId trackId, const audio::AudioResourceId& resourceId) const override;
|
||||
AudioResourceIdList resolveResources() const override;
|
||||
audio::AudioResourceMetaList resolveResources() const override;
|
||||
|
||||
void refresh() override;
|
||||
|
||||
|
|
|
@ -57,14 +57,14 @@ ISynthesizerPtr SynthResolver::resolveSynth(const TrackId trackId, const AudioIn
|
|||
|
||||
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()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -74,7 +74,7 @@ ISynthesizerPtr SynthResolver::resolveDefaultSynth(const TrackId trackId) const
|
|||
return resolveSynth(trackId, m_defaultInputParams);
|
||||
}
|
||||
|
||||
AudioResourceIdList SynthResolver::resolveAvailableResources(const AudioSourceType type) const
|
||||
AudioResourceMetaList SynthResolver::resolveAvailableResources() const
|
||||
{
|
||||
ONLY_AUDIO_WORKER_THREAD;
|
||||
|
||||
|
@ -82,14 +82,14 @@ AudioResourceIdList SynthResolver::resolveAvailableResources(const AudioSourceTy
|
|||
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
auto search = m_resolvers.find(type);
|
||||
AudioResourceMetaList result;
|
||||
|
||||
if (search != m_resolvers.end()) {
|
||||
return search->second->resolveResources();
|
||||
for (const auto& pair : m_resolvers) {
|
||||
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 {};
|
||||
return result;
|
||||
}
|
||||
|
||||
void SynthResolver::registerResolver(const AudioSourceType type, IResolverPtr resolver)
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
|
||||
ISynthesizerPtr resolveSynth(const TrackId trackId, const AudioInputParams& params) 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;
|
||||
|
||||
|
|
|
@ -119,17 +119,13 @@ Channel<AudioOutputParams> AudioOutputHandler::masterOutputParamsChanged() const
|
|||
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,
|
||||
Promise<AudioResourceIdList>::Reject reject) {
|
||||
return Promise<AudioResourceMetaList>([this](Promise<AudioResourceMetaList>::Resolve resolve,
|
||||
Promise<AudioResourceMetaList>::Reject /*reject*/) {
|
||||
ONLY_AUDIO_WORKER_THREAD;
|
||||
|
||||
if (type == AudioFxType::Undefined) {
|
||||
reject(static_cast<int>(Err::InvalidFxParams), "unable to get resources for undefined fx type");
|
||||
}
|
||||
|
||||
resolve(fxResolver()->resolveAvailableResources(type));
|
||||
resolve(fxResolver()->resolveAvailableResources());
|
||||
}, AudioThread::ID);
|
||||
}
|
||||
|
||||
|
@ -143,6 +139,7 @@ Promise<AudioSignalChanges> AudioOutputHandler::signalChanges(const TrackSequenc
|
|||
|
||||
if (!s) {
|
||||
reject(static_cast<int>(Err::InvalidSequenceId), "invalid sequence id");
|
||||
return;
|
||||
}
|
||||
|
||||
resolve({ s->audioIO()->signalAmplitudeChanged(trackId), s->audioIO()->volumePressureChanged(trackId) });
|
||||
|
|
|
@ -47,7 +47,7 @@ public:
|
|||
void setMasterOutputParams(const AudioOutputParams& params) 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> masterSignalChanges() const override;
|
||||
|
|
|
@ -150,17 +150,13 @@ Channel<TrackSequenceId, TrackId> TracksHandler::trackRemoved() const
|
|||
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,
|
||||
Promise<AudioResourceIdList>::Reject reject) {
|
||||
return Promise<AudioResourceMetaList>([this](Promise<AudioResourceMetaList>::Resolve resolve,
|
||||
Promise<AudioResourceMetaList>::Reject /*reject*/) {
|
||||
ONLY_AUDIO_WORKER_THREAD;
|
||||
|
||||
if (type == AudioSourceType::Undefined) {
|
||||
reject(static_cast<int>(Err::InvalidAudioSourceParams), "unable to get resources for undefined audio source type");
|
||||
}
|
||||
|
||||
resolve(resolver()->resolveAvailableResources(type));
|
||||
resolve(resolver()->resolveAvailableResources());
|
||||
}, AudioThread::ID);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ public:
|
|||
~TracksHandler();
|
||||
|
||||
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,
|
||||
AudioParams&& params) override;
|
||||
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> 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;
|
||||
void setInputParams(const TrackSequenceId sequenceId, const TrackId trackId, const AudioInputParams& params) override;
|
||||
|
|
|
@ -49,12 +49,16 @@ void VstPluginListModelExample::load()
|
|||
<< "error text: " << text;
|
||||
});
|
||||
|
||||
playback()->tracks()->availableInputResources(audio::AudioSourceType::Vsti)
|
||||
.onResolve(this, [this](AudioResourceIdList idList) {
|
||||
playback()->tracks()->availableInputResources()
|
||||
.onResolve(this, [this](AudioResourceMetaList resourceList) {
|
||||
QVariantList list;
|
||||
|
||||
for (const AudioResourceId& id : idList) {
|
||||
QVariantMap item = { { "value", QString::fromStdString(id) } };
|
||||
for (const auto& meta : resourceList) {
|
||||
if (meta.type != AudioResourceType::VstPlugin) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QVariantMap item = { { "value", QString::fromStdString(meta.id) } };
|
||||
list << item;
|
||||
}
|
||||
setAvailableSynthResources(list);
|
||||
|
@ -65,12 +69,12 @@ void VstPluginListModelExample::load()
|
|||
<< "error text: " << text;
|
||||
});
|
||||
|
||||
playback()->audioOutput()->availableOutputResources(audio::AudioFxType::Vst)
|
||||
.onResolve(this, [this](AudioResourceIdList idList) {
|
||||
playback()->audioOutput()->availableOutputResources()
|
||||
.onResolve(this, [this](AudioResourceMetaList resources) {
|
||||
QVariantList list;
|
||||
|
||||
for (const AudioResourceId& id : idList) {
|
||||
QVariantMap item = { { "value", QString::fromStdString(id) } };
|
||||
for (const auto& meta : resources) {
|
||||
QVariantMap item = { { "value", QString::fromStdString(meta.id) } };
|
||||
list << item;
|
||||
}
|
||||
setAvailableFxResources(list);
|
||||
|
@ -209,8 +213,7 @@ const QString& VstPluginListModelExample::currentSynthResource() const
|
|||
void VstPluginListModelExample::applyNewInputParams()
|
||||
{
|
||||
AudioInputParams inputParams;
|
||||
inputParams.type = AudioSourceType::Vsti;
|
||||
inputParams.resourceId = m_currentSynthResource.toStdString();
|
||||
inputParams.resourceMeta.id = m_currentSynthResource.toStdString();
|
||||
|
||||
playback()->tracks()->setInputParams(m_currentSequenceId, m_currentTrackId, inputParams);
|
||||
}
|
||||
|
@ -218,11 +221,10 @@ void VstPluginListModelExample::applyNewInputParams()
|
|||
void VstPluginListModelExample::applyNewOutputParams()
|
||||
{
|
||||
AudioFxParams fxParams;
|
||||
fxParams.type = AudioFxType::Vst;
|
||||
fxParams.resourceId = m_currentFxResource.toStdString();
|
||||
fxParams.resourceMeta.id = m_currentFxResource.toStdString();
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -33,12 +33,12 @@ VstFxProcessor::VstFxProcessor(VstPluginPtr&& pluginPtr)
|
|||
|
||||
void VstFxProcessor::init()
|
||||
{
|
||||
m_vstAudioClient->init(m_pluginPtr);
|
||||
m_vstAudioClient->init(VstPluginType::Fx, m_pluginPtr);
|
||||
}
|
||||
|
||||
AudioFxType VstFxProcessor::type() const
|
||||
{
|
||||
return audio::AudioFxType::Vst;
|
||||
return audio::AudioFxType::VstFx;
|
||||
}
|
||||
|
||||
void VstFxProcessor::setSampleRate(unsigned int sampleRate)
|
||||
|
|
|
@ -35,18 +35,12 @@ std::vector<IFxProcessorPtr> VstFxResolver::resolveFxList(const audio::TrackId t
|
|||
return {};
|
||||
}
|
||||
|
||||
AudioResourceIdList newResourcesidList;
|
||||
|
||||
for (const auto& param : fxParams) {
|
||||
newResourcesidList.emplace_back(param.resourceId);
|
||||
}
|
||||
|
||||
FxMap& fxMap = m_tracksFxMap[trackId];
|
||||
updateTrackFxMap(fxMap, trackId, newResourcesidList);
|
||||
updateTrackFxMap(fxMap, trackId, fxParams);
|
||||
|
||||
std::vector<IFxProcessorPtr> result;
|
||||
|
||||
for (const auto& pair : m_masterFxMap) {
|
||||
for (const auto& pair : fxMap) {
|
||||
result.emplace_back(pair.second);
|
||||
}
|
||||
|
||||
|
@ -60,13 +54,7 @@ std::vector<IFxProcessorPtr> VstFxResolver::resolveMasterFxList(const std::vecto
|
|||
return {};
|
||||
}
|
||||
|
||||
AudioResourceIdList newResourcesidList;
|
||||
|
||||
for (const auto& param : fxParams) {
|
||||
newResourcesidList.emplace_back(param.resourceId);
|
||||
}
|
||||
|
||||
updateMasterFxMap(newResourcesidList);
|
||||
updateMasterFxMap(fxParams);
|
||||
|
||||
std::vector<IFxProcessorPtr> result;
|
||||
|
||||
|
@ -77,9 +65,9 @@ std::vector<IFxProcessorPtr> VstFxResolver::resolveMasterFxList(const std::vecto
|
|||
return result;
|
||||
}
|
||||
|
||||
AudioResourceIdList VstFxResolver::resolveResources() const
|
||||
AudioResourceMetaList VstFxResolver::resolveResources() const
|
||||
{
|
||||
return pluginModulesRepo()->moduleIdList(VstPluginType::Fx);
|
||||
return pluginModulesRepo()->fxModulesMeta();
|
||||
}
|
||||
|
||||
void VstFxResolver::refresh()
|
||||
|
@ -121,15 +109,20 @@ VstFxPtr VstFxResolver::createTrackFx(const audio::TrackId trackId, const audio:
|
|||
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;
|
||||
for (const auto& pair : fxMap) {
|
||||
currentResourceIdList.emplace_back(pair.first);
|
||||
}
|
||||
|
||||
AudioResourceIdList newResourcesidList;
|
||||
for (const auto& param : fxParams) {
|
||||
newResourcesidList.emplace_back(param.resourceMeta.id);
|
||||
}
|
||||
|
||||
audio::AudioResourceIdList idListToRemove;
|
||||
fxListToRemove(newResourceIdList, currentResourceIdList, idListToRemove);
|
||||
fxListToRemove(newResourcesidList, currentResourceIdList, idListToRemove);
|
||||
|
||||
for (const auto& idToRemove : idListToRemove) {
|
||||
pluginsRegister()->unregisterFxPlugin(trackId, idToRemove);
|
||||
|
@ -137,22 +130,32 @@ void VstFxResolver::updateTrackFxMap(FxMap& fxMap, const audio::TrackId trackId,
|
|||
}
|
||||
|
||||
audio::AudioResourceIdList idListToCreate;
|
||||
fxListToCreate(newResourceIdList, currentResourceIdList, idListToCreate);
|
||||
fxListToCreate(newResourcesidList, currentResourceIdList, idListToCreate);
|
||||
|
||||
for (const auto& idToCreate : idListToCreate) {
|
||||
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;
|
||||
for (const auto& pair : m_masterFxMap) {
|
||||
currentResourceIdList.emplace_back(pair.first);
|
||||
}
|
||||
|
||||
AudioResourceIdList newResourcesidList;
|
||||
for (const auto& param : fxParams) {
|
||||
newResourcesidList.emplace_back(param.resourceMeta.id);
|
||||
}
|
||||
|
||||
audio::AudioResourceIdList idListToRemove;
|
||||
fxListToRemove(newResourceIdList, currentResourceIdList, idListToRemove);
|
||||
fxListToRemove(newResourcesidList, currentResourceIdList, idListToRemove);
|
||||
|
||||
for (const auto& idToRemove : idListToRemove) {
|
||||
pluginsRegister()->unregisterMasterFxPlugin(idToRemove);
|
||||
|
@ -160,11 +163,16 @@ void VstFxResolver::updateMasterFxMap(const audio::AudioResourceIdList& newResou
|
|||
}
|
||||
|
||||
audio::AudioResourceIdList idListToCreate;
|
||||
fxListToCreate(newResourceIdList, currentResourceIdList, idListToCreate);
|
||||
fxListToCreate(newResourcesidList, currentResourceIdList, idListToCreate);
|
||||
|
||||
for (const auto& idToCreate : idListToCreate) {
|
||||
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,
|
||||
|
|
|
@ -47,7 +47,7 @@ public:
|
|||
std::vector<audio::IFxProcessorPtr> resolveFxList(const audio::TrackId trackId,
|
||||
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;
|
||||
|
||||
private:
|
||||
|
@ -56,8 +56,8 @@ private:
|
|||
VstFxPtr createMasterFx(const audio::AudioResourceId& resourceId) const;
|
||||
VstFxPtr createTrackFx(const audio::TrackId trackId, const audio::AudioResourceId& resourceId) const;
|
||||
|
||||
void updateMasterFxMap(const audio::AudioResourceIdList& newResourceIdList);
|
||||
void updateTrackFxMap(FxMap& fxMap, const audio::TrackId trackId, const audio::AudioResourceIdList& newResourceIdList);
|
||||
void updateMasterFxMap(const std::vector<audio::AudioFxParams>& fxParams);
|
||||
void updateTrackFxMap(FxMap& fxMap, const audio::TrackId trackId, const std::vector<audio::AudioFxParams>& fxParams);
|
||||
|
||||
void fxListToRemove(const audio::AudioResourceIdList& currentResourceIdList, const audio::AudioResourceIdList& newResourceIdList,
|
||||
audio::AudioResourceIdList& resultList);
|
||||
|
|
|
@ -67,7 +67,7 @@ VstSynthPtr VstiResolver::createSynth(const audio::TrackId trackId, const audio:
|
|||
return synth;
|
||||
}
|
||||
|
||||
AudioResourceIdList VstiResolver::resolveResources() const
|
||||
AudioResourceMetaList VstiResolver::resolveResources() const
|
||||
{
|
||||
return pluginModulesRepo()->moduleIdList(VstPluginType::Instrument);
|
||||
return pluginModulesRepo()->instrumentModulesMeta();
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ class VstiResolver : public audio::synth::ISynthResolver::IResolver
|
|||
INJECT(vst, IVstPluginsRegister, pluginsRegister)
|
||||
public:
|
||||
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;
|
||||
|
||||
private:
|
||||
|
|
|
@ -65,36 +65,22 @@ PluginModulePtr VstModulesRepository::pluginModule(const audio::AudioResourceId&
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
audio::AudioResourceIdList VstModulesRepository::moduleIdList(const VstPluginType& type) const
|
||||
audio::AudioResourceMetaList VstModulesRepository::instrumentModulesMeta() const
|
||||
{
|
||||
ONLY_AUDIO_THREAD(threadSecurer);
|
||||
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
audio::AudioResourceIdList result;
|
||||
return modulesMetaList(VstPluginType::Instrument);
|
||||
}
|
||||
|
||||
if (type == VstPluginType::Undefined) {
|
||||
return result;
|
||||
}
|
||||
audio::AudioResourceMetaList VstModulesRepository::fxModulesMeta() const
|
||||
{
|
||||
ONLY_AUDIO_THREAD(threadSecurer);
|
||||
|
||||
for (const auto& pair : m_modules) {
|
||||
PluginModulePtr module = pair.second;
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
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) {
|
||||
result.emplace_back(pair.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return modulesMetaList(VstPluginType::Fx);
|
||||
}
|
||||
|
||||
void VstModulesRepository::refresh()
|
||||
|
@ -128,6 +114,45 @@ void VstModulesRepository::addModule(const io::path& path)
|
|||
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> pluginPaths = fileSystem()->scanFiles(customPath, QStringList(QString::fromStdString(VST3_PACKAGE_EXTENSION)));
|
||||
|
|
|
@ -48,11 +48,14 @@ public:
|
|||
void init();
|
||||
|
||||
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;
|
||||
|
||||
private:
|
||||
void addModule(const io::path& path);
|
||||
audio::AudioResourceMetaList modulesMetaList(const VstPluginType& type) const;
|
||||
|
||||
RetVal<io::paths> pluginPathsFromCustomLocation(const io::path& customPath) const;
|
||||
PluginModule::PathList pluginPathsFromDefaultLocation() const;
|
||||
|
|
|
@ -37,7 +37,8 @@ public:
|
|||
virtual ~IVstModulesRepository() = default;
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -74,8 +74,7 @@ void ProjectAudioSettings::makeDefault()
|
|||
AudioInputParams ProjectAudioSettings::inputParamsFromJson(const QJsonObject& object) const
|
||||
{
|
||||
AudioInputParams result;
|
||||
result.type = sourceTypeFromString(object.value("type").toString());
|
||||
result.resourceId = object.value("resourceId").toString().toStdString();
|
||||
result.resourceMeta.id = object.value("resourceId").toString().toStdString();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -93,8 +92,8 @@ AudioOutputParams ProjectAudioSettings::outputParamsFromJson(const QJsonObject&
|
|||
QJsonObject ProjectAudioSettings::inputParamsToJson(const audio::AudioInputParams& params) const
|
||||
{
|
||||
QJsonObject result;
|
||||
result.insert("type", sourceTypeToString(params.type));
|
||||
result.insert("resourceId", QString::fromStdString(params.resourceId));
|
||||
result.insert("type", sourceTypeToString(params.type()));
|
||||
result.insert("resourceId", QString::fromStdString(params.resourceMeta.id));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue