Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
135 commits
Select commit Hold shift + click to select a range
9c80041
Add CLAP 1.1.3 submodule
messmerd Dec 31, 2023
7b630bd
Add submodule again; Add CLAP to CMake
messmerd Dec 31, 2023
b443722
Remove CLAP submodule from old location
messmerd Dec 31, 2023
c51390c
Locate and init CLAP plugins
messmerd Dec 19, 2022
5e2866e
Add CLAP logo
messmerd Jan 22, 2023
ae61e5c
Update CLAP to version 1.1.6
messmerd Jan 22, 2023
1e17502
Add clap-helpers submodule
messmerd Jan 24, 2023
4992b2a
Refactor ClapManager
messmerd Jan 29, 2023
1617b05
Move ClapFile/ClapPlugin into their own source files
messmerd Jan 29, 2023
b088038
Add PluginIssueHash
messmerd Dec 31, 2023
230c953
Add missing ClapFile.h/cpp; Start implementing ClapPorts
messmerd Jan 29, 2023
2469d9f
Add ClapSubPluginFeatures
messmerd Jan 29, 2023
3de14c1
Add ClapEffect (currently non-functional)
messmerd Jan 29, 2023
ed63855
Improve effect description widget text
messmerd Jan 29, 2023
ee87f4e
Refactor to support plugin instances
messmerd Jan 30, 2023
987c9ff
More refactoring
messmerd Jan 31, 2023
10f48a6
Refactor + fix ownership issues
messmerd Feb 2, 2023
c20c075
Progress
messmerd Feb 13, 2023
1763e5a
Fix audio buffers and plugin state
messmerd Feb 13, 2023
0dd0905
Copy audio buffers; Implement CLAP_EXT_LOG
messmerd Feb 17, 2023
c3821d9
Fix crash when initializing some CLAP plugins
messmerd Feb 17, 2023
ec27096
Allocate audio buffers - some CLAP effects work now
messmerd Feb 17, 2023
4bede10
Fix crash, implement thread check extension, and more
messmerd Feb 24, 2023
35c7dcf
Fix edge case
messmerd Feb 24, 2023
c891ab2
Begin implementing params
messmerd Feb 26, 2023
01e2dd8
Minor changes
messmerd Mar 12, 2023
c1827fa
Progress on params
messmerd Mar 12, 2023
cdfea27
Parameter automation mostly works now
messmerd Mar 12, 2023
961e4f8
Use CheckControl; Minor improvements
messmerd Mar 13, 2023
b5b6ae3
Modify CustomTextKnob to provide "dynamic" text option
messmerd Dec 31, 2023
72e8034
Implement ClapControlBase::reload()
messmerd Apr 30, 2023
2fb00cc
Fix failed assert
messmerd May 1, 2023
cc397ab
Fix build
messmerd Dec 31, 2023
1c2326b
Update CLAP to version 1.1.8
messmerd Aug 28, 2023
7f171e3
Update clap-helpers
messmerd Aug 28, 2023
346595d
Fix crash when loading LSP plugin ports
messmerd Aug 28, 2023
b1923ff
Safer param creation
messmerd Sep 24, 2023
b3cb37e
Style fixes + better memory/thread safety
messmerd Sep 24, 2023
983838d
Fix build
messmerd Sep 25, 2023
a9cc62e
Stop using RTLD_DEEPBIND to allow ASan to work; Modify method names
messmerd Sep 25, 2023
eaf8f77
Fail gracefully when plugin parameter is invalid
messmerd Sep 25, 2023
dc32273
Implement transport event; Better state transitions
messmerd Dec 31, 2023
ca41492
Fix CLAP file deinit; Fix some memory issues; Minor changes
messmerd Sep 28, 2023
fe6166d
Use ArrayVector
messmerd Sep 30, 2023
8c4f78f
Param init improvements; Minor changes
messmerd Sep 30, 2023
084acd6
Add empty latency extension impl to prevent DISTRHO plugin crashes
messmerd Oct 1, 2023
2abc80d
Start implementing CLAP instruments
messmerd Oct 2, 2023
a0dd5fc
Ensure CLAP plugins start on main thread
messmerd Oct 2, 2023
7b38b5e
Fix null pointer dereference when input port doesn't exist
messmerd Oct 2, 2023
c37346a
Use ringbuffer for midi events
messmerd Oct 4, 2023
b782016
Support steady time
messmerd Oct 4, 2023
5e64b1e
Implement transport beats info; Set transport flags correctly
messmerd Oct 5, 2023
03773ba
Add ClapTransport class
messmerd Oct 6, 2023
77975ac
Refactor some window embedding code in preparation for CLAP GUI
messmerd Dec 31, 2023
4a48daf
Fix regression from previous commit
messmerd Oct 8, 2023
6919eef
Begin GUI implementation; Don't set constant_mask
messmerd Oct 10, 2023
63a356a
Implement MIDI key pressure event
messmerd Oct 10, 2023
0e3bbb8
Allow LMMS_CLAP_PATH env var to override all default CLAP search paths
messmerd Oct 11, 2023
1fdbaab
Attempt to fix restart method; Reimplement constant_mask
messmerd Oct 11, 2023
3e96224
Fix restart() and deactivate()
messmerd Oct 12, 2023
1f95248
Improve param value text; Improve extension init
messmerd Oct 22, 2023
70e817d
Implement note ports extension; Refactor log extension
messmerd Nov 2, 2023
8b2b2c2
Fix filesystem includes; Fix value_to_text() buffer size
messmerd Nov 3, 2023
9439574
Fix build
messmerd Nov 3, 2023
e5f2ceb
Fix some build issues
messmerd Nov 5, 2023
5ecfb76
Improve findSearchPaths()
messmerd Dec 4, 2023
bbdc9ae
Better way of ensuring plugins load on main thread
messmerd Dec 4, 2023
2b9e996
Fix some issues
messmerd Dec 4, 2023
599fe47
Fix scripted-checks
messmerd Dec 4, 2023
d872221
Update CLAP to version 1.1.10
messmerd Dec 4, 2023
27b4ea2
Fix instruments that have audio input
messmerd Dec 17, 2023
bbf328c
Use mingw.thread.h
messmerd Dec 17, 2023
5661141
Implement timer support extension
messmerd Dec 21, 2023
076511e
Improve timer support
messmerd Dec 21, 2023
1b18171
Implement thread pool extension
messmerd Dec 22, 2023
71c3095
Enable thread pool extension
messmerd Dec 22, 2023
3b0dea0
Begin refactoring CLAP extensions
messmerd Dec 24, 2023
08ac8cc
Continue refactoring CLAP extensions
messmerd Dec 24, 2023
7d9b581
Implement state extension (WIP)
messmerd Dec 27, 2023
bf7f600
Refactor thread check and params extensions (WIP)
messmerd Dec 29, 2023
f5dbc3b
Refactor gui extension
messmerd Dec 29, 2023
2c7e10f
Fix mistake in thread check extension
messmerd Dec 31, 2023
88386ec
Workaround for std::experimental::filesystem
messmerd Dec 31, 2023
6e83350
Refactor log extension
messmerd Jan 1, 2024
ba29c87
Fix build; Remove thread pool extension (needs more work)
messmerd Jan 2, 2024
337e5ca
Try to fix filesystem issues
messmerd Jan 2, 2024
80c5643
Try to fix builds
messmerd Jan 2, 2024
90a5b15
Clean up includes
messmerd Jan 3, 2024
189e142
More refactoring
messmerd Jan 3, 2024
5972559
Fix MSVC build
messmerd Jan 16, 2024
f654a1d
Cleanup; Use CLAP state when cloning tracks (WIP)
messmerd Jan 22, 2024
a5c4097
Fix state extension implementation and plugin cloning
messmerd Jan 23, 2024
e50d007
Update CLAP to version 1.2.0
messmerd Jan 26, 2024
f04a5bb
Add support for CLAP compatibility IDs; revert parameter value change
messmerd Jan 27, 2024
5af3d4d
Add hashCombine function
messmerd Feb 9, 2024
ad7bd3e
Begin work on presets (WIP)
messmerd Feb 11, 2024
60374db
More work on presets
messmerd Feb 12, 2024
73e3fde
Fix small timer support bug
messmerd Feb 12, 2024
dfe8ac4
Fix some issues in ClapPresetLoader::load()
messmerd Feb 13, 2024
63ef03d
More work on CLAP presets (WIP)
messmerd Feb 20, 2024
21d9168
Remember to deinit preset database
messmerd Feb 20, 2024
698d1c9
CLAP presets (WIP)
messmerd Mar 3, 2024
e502ad3
More progress on presets (WIP)
messmerd Mar 4, 2024
3c54c31
Try to fix build
messmerd Mar 7, 2024
bf85afe
Implement state context extension
messmerd Mar 7, 2024
763d69a
Presets and parameters (WIP)
messmerd Mar 9, 2024
575dd78
Presets bug fixes and refactoring (WIP)
messmerd Mar 16, 2024
148f5fc
Fix external presets
messmerd Mar 17, 2024
7e6dd39
Fix PresetSelector
messmerd Mar 17, 2024
c1662aa
Add preset load/save buttons; cleanup
messmerd Mar 18, 2024
feee422
Allow extension initialization within plugin.init() call
messmerd Mar 21, 2024
5b6bb75
Merge branch 'LMMS:master' into clap-host-dev
messmerd Mar 21, 2024
6063cdf
Fix ClapState::save() bug
messmerd Mar 23, 2024
1aac7a9
Add CLAP filter to EffectSelectDialog
messmerd Mar 24, 2024
f29e8ca
Minor changes
messmerd Mar 24, 2024
cb09644
New way of handling mono plugins (WIP)
messmerd Mar 26, 2024
92ebcf7
Remove LinkedModelGroup usage
messmerd Mar 27, 2024
3e5b433
Improve PluginPortConfig
messmerd Mar 28, 2024
d17a1d8
Add PluginPortConfigSelector
messmerd Mar 28, 2024
090bf82
Replace QComboBox with ComboBox
messmerd Mar 28, 2024
2b8e8d8
Fix Windows builds
messmerd Mar 28, 2024
f896536
Delay full extension init until after plugin.init()
messmerd Mar 29, 2024
b660556
Fix automation load/save regression
messmerd Apr 6, 2024
52b1214
Merge branch 'master' of https://github.com/messmerd/lmms into clap-h…
messmerd Apr 7, 2024
da893e2
Fix build
messmerd Apr 7, 2024
2b23635
Fix CLAP loading on macOS
messmerd Apr 18, 2024
1808474
Merge branch 'master' into clap-host-dev
messmerd May 28, 2024
4201279
Use std::filesystem; fix UTF-8 issues
messmerd May 29, 2024
0a3cb05
Fix build
messmerd May 29, 2024
b7ed5a0
Merge branch 'master' into clap-host-dev
messmerd Nov 7, 2024
0dec314
Fix build
messmerd Nov 7, 2024
1b3b091
Fix more build errors
messmerd Nov 7, 2024
5470871
Merge branch 'master' into clap-host-dev
messmerd Jul 6, 2025
0ca27e2
Fix C++20 upgrade issues
messmerd Jul 6, 2025
5f3f699
Fix MSVC build
messmerd Jul 6, 2025
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
Prev Previous commit
Next Next commit
Presets bug fixes and refactoring (WIP)
  • Loading branch information
messmerd committed Mar 16, 2024
commit 575dd784407caac69dd4b1a1d025734b120df8a9
33 changes: 19 additions & 14 deletions include/ClapPresetDatabase.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <clap/factory/preset-discovery.h>

#include "ClapExtension.h"
#include "lmms_filesystem.h"
#include "NoCopyNoMove.h"
#include "PresetDatabase.h"

Expand All @@ -53,8 +54,6 @@ class ClapPresetDatabase : public PresetDatabase
auto init(const clap_plugin_entry* entry) -> bool;
void deinit();

auto discover() -> bool override;

auto supported() const -> bool { return m_factory; }

static auto toClapLocation(std::string_view location, std::string& ref)
Expand All @@ -64,7 +63,13 @@ class ClapPresetDatabase : public PresetDatabase
const char* location, const char* loadKey) -> std::optional<PresetLoadData>;

private:
auto createPreset(const Preset::LoadData& loadData) const -> std::optional<Preset> override;
auto discoverSetup() -> bool override;
auto discoverFiletypes(std::vector<Filetype>& filetypes) -> bool override;
auto discoverLocations(const SetLocations& func) -> bool override;
auto discoverPresets(const Location& location, std::set<Preset>& presets) -> bool override;

auto loadPresets(const Location& location, std::string_view file, std::set<Preset>& presets)
-> std::vector<const Preset*> override;

class Indexer : public NoCopyNoMove
{
Expand All @@ -77,19 +82,17 @@ class ClapPresetDatabase : public PresetDatabase
const clap_preset_discovery_provider_descriptor& descriptor);
~Indexer() = default;

auto query(std::string_view location, PresetMetadata::Flags flags = PresetMetadata::Flag::None)
//! For PLUGIN presets
auto query(PresetMetadata::Flags flags = PresetMetadata::Flag::None)
-> std::optional<std::vector<Preset>>;

auto provider() const -> const clap_preset_discovery_provider* { return m_provider.get(); }
//! For FILE presets; `file` is the full path of the preset file
auto query(std::string_view file,
PresetMetadata::Flags flags = PresetMetadata::Flag::None) -> std::optional<std::vector<Preset>>;

//! Like clap_preset_discovery_location, for storing declare_location() data
struct Location
{
PresetMetadata::Flags flags;
std::string name;
clap_preset_discovery_location_kind kind;
std::string location; //!< PathUtil-compatible
};
auto filetypeSupported(fs::path path) const -> bool;

auto provider() const -> const clap_preset_discovery_provider* { return m_provider.get(); }

auto locations() -> auto& { return m_locations; }
auto filetypes() -> auto& { return m_filetypes; }
Expand Down Expand Up @@ -118,10 +121,12 @@ class ClapPresetDatabase : public PresetDatabase
clap_preset_discovery_indexer m_indexer;
std::unique_ptr<const clap_preset_discovery_provider, ProviderDeleter> m_provider;

std::vector<Location> m_locations;
std::vector<PresetDatabase::Location> m_locations;
std::vector<PresetDatabase::Filetype> m_filetypes;
};

auto getIndexerFor(const Location& location) const -> Indexer*;

class MetadataReceiver;

const clap_preset_discovery_factory* m_factory = nullptr;
Expand Down
34 changes: 6 additions & 28 deletions include/Preset.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@

#include "Flags.h"
#include "NoCopyNoMove.h"
//#include "Plugin.h"

namespace lmms
{
Expand All @@ -42,26 +41,22 @@ struct PresetLoadData
{
/**
* A string that can be parsed by PathUtil.
* Its meaning depends on the plugin, but it typically represents a preset directory.
* Its meaning depends on the plugin, but it typically represents a preset file path.
*
* Valid examples:
* - "userprojects:"
* - "preset:MyPlugin/MyFavoritePresets"
* - "/my/absolute/directory"
* - "preset:my_plugin/my_preset_database.txt" (depending on the plugin, it could even be a file!)
* - "preset:MyPlugin/MyFavoritePresets/foo.preset"
* - "/my/absolute/directory/bar.ext"
* - "preset:foo/preset_database.txt" (could be a container of presets, in which case `loadKey` is non-empty)
* - "internal:" (for presets stored within the plugin's DSO rather than on disk)
*/
std::string location;

/**
* Could be a preset filename, sub-path + preset filename, file offset, or any other kind of unique ID.
* If non-empty, could be a file offset or any other kind of unique ID.
* Again, it's entirely up to the plugin.
*/
std::string loadKey;

// Whether `location` and `loadKey` can be concatenated together
// to form a single string depends entirely on the plugin.

friend auto operator==(const PresetLoadData& lhs, const PresetLoadData& rhs) -> bool
{
return lhs.location == rhs.location && lhs.loadKey == rhs.loadKey;
Expand Down Expand Up @@ -95,23 +90,6 @@ LMMS_DECLARE_OPERATORS_FOR_FLAGS(PresetMetadata::Flag)
class Preset
{
public:
/**
* Same as `PresetLoadData`, but `location` is a std::string_view that references a key
* within `PresetDatabase::m_presets` in order to save space when many presets are loaded.
*/
struct LoadData
{
std::string_view location;
std::string loadKey;

friend auto operator==(const LoadData& lhs, const PresetLoadData& rhs) noexcept -> bool
{
return lhs.location == rhs.location && lhs.loadKey == rhs.loadKey;
}

operator PresetLoadData() const { return {std::string{location}, loadKey}; }
};

auto metadata() -> auto& { return m_metadata; }
auto metadata() const -> auto& { return m_metadata; }

Expand All @@ -135,7 +113,7 @@ class Preset

private:
PresetMetadata m_metadata;
LoadData m_loadData;
PresetLoadData m_loadData;

//! Subplugin keys that support this preset
//! Empty if all subplugins support the preset or if there are no subplugins
Expand Down
140 changes: 95 additions & 45 deletions include/PresetDatabase.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,48 +42,71 @@ namespace lmms
* Plugins are expected to inherit this class to implement preset discovery,
* metadata loading, and other functionality.
*/
class PresetDatabase : public NoCopyNoMove
class PresetDatabase
{
public:
using PresetMap = std::map<std::string, std::set<Preset>, std::less<>>;

struct Filetype
{
std::string name;
std::string description;
std::string extension;
std::string extension; //< without dot; if empty, any extension is supported
};

//! Represents a preset directory or internal location where presets can be found
struct Location
{
std::string name;
std::string location; //!< PathUtil-compatible
PresetMetadata::Flags flags = PresetMetadata::Flag::None;

friend auto operator==(const Location& lhs, const Location& rhs) noexcept -> bool
{
return lhs.location == rhs.location;
}

friend auto operator<(const Location& lhs, const Location& rhs) noexcept -> bool
{
return lhs.location < rhs.location;
}

friend auto operator<(std::string_view location, const Location& rhs) noexcept -> bool
{
return location < rhs.location;
}

friend auto operator<(const Location& lhs, std::string_view location) noexcept -> bool
{
return lhs.location < location;
}
};

using PresetMap = std::map<Location, std::set<Preset>, std::less<>>;

PresetDatabase() = default;
//using QObject::QObject;
//PresetDatabase(std::string_view key);
virtual ~PresetDatabase() = default;

//! Discover presets and populate database; Returns true when successful
virtual auto discover() -> bool = 0;
auto discover() -> bool;

//! Load a preset file from disk; Returns nullptr upon failure or if preset was already added
auto addPreset(std::string_view path) -> const Preset*;
//! Load a preset file from disk; Returns empty vector upon failure or if preset(s) were already added
auto addPresets(std::string_view path) -> std::vector<const Preset*>;

/**
* Accessors
*/

auto presets() const -> auto& { return m_presets; }

auto presets(const std::string& location) const -> const std::set<Preset>&
{
return m_presets.at(location);
}

auto presets(const std::string& location) -> std::set<Preset>&
auto presets(std::string_view location) const -> const std::set<Preset>*
{
return m_presets.at(location);
const auto it = m_presets.find(location);
return it != m_presets.end() ? &it->second : nullptr;
}

auto presets(std::string_view location) -> PresetMap::iterator
auto presets(std::string_view location) -> std::set<Preset>*
{
return m_presets.find(location);
const auto it = m_presets.find(location);
return it != m_presets.end() ? &it->second : nullptr;
}

auto filetypes() const -> auto& { return m_filetypes; }
Expand All @@ -94,7 +117,7 @@ class PresetDatabase : public NoCopyNoMove
auto findPreset(const PresetLoadData& loadData, std::string_view key = std::string_view{}) const -> const Preset*;

//! Open preset dialog TODO: Move to an lmms::gui class?
auto openPresetFile(std::string_view previousFile) -> const Preset*;
auto openPresetFile(std::string_view previousFile) -> std::vector<const Preset*>;

//! Save preset dialog TODO: Move to an lmms::gui class?
auto savePresetFile(const Preset& preset) -> bool;
Expand All @@ -106,43 +129,70 @@ class PresetDatabase : public NoCopyNoMove

protected:

//! Creates a populated Preset object from Preset::LoadData.
//! Plugins should override this to provide better preset metadata.
virtual auto createPreset(const Preset::LoadData& loadData) const -> std::optional<Preset>;
/**
* 1st step of `discover()` - optional setup
*
* Return true if successful
*/
virtual auto discoverSetup() -> bool { return true; }

/**
* 2nd step of `discover()` - declare all supported file types
*
* Return true if successful
*/
virtual auto discoverFiletypes(std::vector<Filetype>& filetypes) -> bool = 0;

//! Creates a populated Preset object from Preset::LoadData and key(s).
//! Plugins should override this to provide better preset metadata.
virtual auto createPreset(const Preset::LoadData& loadData,
const std::vector<std::string>& keys) const -> std::optional<Preset>;
//! Function object to make `discoverLocations()` implementation simpler and hide implementation details
class SetLocations
{
public:
friend class PresetDatabase;
void operator()(const std::vector<Location>& locations) const;
void operator()(Location location) const;
private:
SetLocations(PresetMap& presets) : m_map{&presets} {}
PresetMap* m_map = nullptr;
};

/**
* Adds a preset file to `m_presets` if it doesn't exist, and returns the load data.
* 3rd step of `discover()` - declare all pre-established preset locations
*
* Checks all the combinations for splitting `path` into location and load key before adding.
* TODO: Return map iterator so that `m_presets` does not need to be searched again?
* Return true if successful
*/
auto addFile(std::string_view path) -> std::optional<Preset::LoadData>;
virtual auto discoverLocations(const SetLocations& func) -> bool = 0;

//! Use during discover() call; The returned iterator is used to add presets at the location
auto addLocation(std::string_view path) -> PresetMap::iterator;
/**
* 4th and final step of `discover()` - populate set of presets at the given location
*
* Return true if successful
*/
virtual auto discoverPresets(const Location& location, std::set<Preset>& presets) -> bool = 0;

//! Use during discover() call
void addFiletype(Filetype filetype)
{
m_filetypes.push_back(std::move(filetype));
}
/**
* Loads presets for the given location from `file`, retrieves any metadata,
* and adds the new presets to `presets`. Returns all the new presets.
*
* Used when the user loads a new preset from disk.
* May also be used by `discoverPresets()`.
*
* The default implementation only works for simple preset files.
* Plugins that support preset containers (where multiple presets could potentially be returned
* from this method) or provide additional preset metadata should reimplement this method.
*/
virtual auto loadPresets(const Location& location, std::string_view file, std::set<Preset>& presets)
-> std::vector<const Preset*>;

//! Use during discover() call
void setFiletypes(std::vector<Filetype> filetypes)
{
m_filetypes = std::move(filetypes);
}
/**
* Gets preset location from `m_presets` which contains `path`, optionally adding it if it doesn't exist
*
* Returns iterator to the `m_presets` location
*/
auto getLocation(std::string_view path, bool add = true) -> PresetMap::iterator;

private:

//! Maps locations to presets.
//! PresetLoadData references this map's key (location), so this map must remain stable after construction.
//! See `PresetLoadData::location` for more info.
//! Maps locations to presets
PresetMap m_presets;

std::vector<Filetype> m_filetypes;
Expand Down
11 changes: 11 additions & 0 deletions src/core/PluginPresets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,23 @@ void PluginPresets::saveActivePreset(QDomDocument& doc, QDomElement& element)

QDomElement presetElement = doc.createElement(presetNodeName());
element.appendChild(presetElement);
qDebug().nospace() << "Saving active preset: location: \"" << location.data() << "\" loadKey: \""
<< loadKey.data() << "\"";
presetElement.setAttribute("location", QString::fromUtf8(location.data(), location.size()));
presetElement.setAttribute("loadKey", QString::fromUtf8(loadKey.data(), loadKey.size()));
}
else
{
qDebug() << "No active preset to save";
}
}

void PluginPresets::loadActivePreset(const QDomElement& element)
{
QDomElement presetElement = element.firstChildElement(presetNodeName());
if (presetElement.isNull())
{
qDebug() << "Loading active preset: None found.";
setActivePreset(std::nullopt);
return;
}
Expand All @@ -173,10 +180,14 @@ void PluginPresets::loadActivePreset(const QDomElement& element)

if (location.isEmpty() && loadKey.isEmpty())
{
qDebug() << "Loading active preset: Active preset data empty.";
setActivePreset(std::nullopt);
return;
}

qDebug().nospace() << "Loading active preset: location: \"" << location.data() << "\" loadKey: \""
<< loadKey.data() << "\"";

// TODO: The needed preset may not be discovered at this point

const auto loadData = PresetLoadData{location.toStdString(), loadKey.toStdString()};
Expand Down
Loading