Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
137 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
b9d18ea
Merge branch 'master' into clap-host-dev
messmerd Jan 7, 2026
f222a1e
Fix build
messmerd Jan 7, 2026
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
Cleanup; Use CLAP state when cloning tracks (WIP)
  • Loading branch information
messmerd committed Jan 27, 2024
commit f654a1d865451f6e58ad3aa825ae36ef03d07373
2 changes: 1 addition & 1 deletion include/ClapControlBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class LMMS_EXPORT ClapControlBase : public LinkedModelGroups
* more functions that must be called from virtuals
*/
auto controlCount() const -> std::size_t;
auto nodeName() const -> QString { return "clapcontrols"; }
auto nodeName() const -> const char* { return "clapcontrols"; }
auto hasNoteInput() const -> bool;
void handleMidiInputEvent(const class MidiEvent& event, const class TimePos& time, f_cnt_t offset);

Expand Down
2 changes: 1 addition & 1 deletion include/ClapExtension.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* ClapExtension.h - Base class template for implementing CLAP extensions
* ClapExtension.h - Base class templates for implementing CLAP extensions
*
* Copyright (c) 2024 Dalton Messmer <messmer.dalton/at/gmail.com>
*
Expand Down
171 changes: 88 additions & 83 deletions include/ClapInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,23 @@ class LMMS_EXPORT ClapInstance final : public QObject
Q_OBJECT;

public:

//! Passkey idiom
class Access
{
public:
friend class ClapInstance;
Access(Access&&) noexcept = default;
private:
Access() {}
Access(const Access&) = default;
};

//! Creates and starts a plugin, returning nullptr if an error occurred
static auto create(const ClapPluginInfo& pluginInfo, Model* parent) -> std::unique_ptr<ClapInstance>;

ClapInstance() = delete;
ClapInstance(const ClapPluginInfo& pluginInfo, Model* parent);
ClapInstance(Access, const ClapPluginInfo& pluginInfo, Model* parent);
~ClapInstance() override;

ClapInstance(const ClapInstance&) = delete;
Expand All @@ -85,33 +100,22 @@ class LMMS_EXPORT ClapInstance final : public QObject

enum class PluginState
{
// The plugin hasn't been created yet or failed to load (NoneWithError)
None,
// The plugin has been created but not initialized
Loaded,
// Initialization failed - LMMS probably does not support this plugin yet
LoadedWithError,
// The plugin is initialized and inactive, only the main thread uses it
Inactive,
// Activation failed
InactiveWithError,
// The plugin is active and sleeping, the audio engine can call set_processing()
ActiveAndSleeping,
// The plugin is processing
None, // Plugin hasn't been created yet or failed to load (NoneWithError)
Loaded, // Plugin has been created but not initialized
LoadedWithError, // Initialization failed - LMMS might not support this plugin yet
Inactive, // Plugin is initialized and inactive, only the main thread uses it
InactiveWithError, // Activation failed
ActiveAndSleeping, // The audio engine can call set_processing()
ActiveAndProcessing,
// The plugin did process but is in error
ActiveWithError,
// The plugin is not used anymore by the audio engine and can be deactivated on the main
// thread
ActiveAndReadyToDeactivate
ActiveWithError, // The plugin did process but an irrecoverable error occurred
ActiveAndReadyToDeactivate // Plugin is unused by audio engine; can deactivate on main thread
};

/////////////////////////////////////////
// LMMS audio thread
/////////////////////////////////////////
/**
* LMMS audio thread
*/

//! Copy values from the LMMS core (connected models, MIDI events, ...) into
//! the respective ports
//! Copy values from the LMMS core (connected models, MIDI events, ...) into the respective ports
void copyModelsFromCore();

//! Bring values from all ports to the LMMS core
Expand All @@ -125,51 +129,29 @@ class LMMS_EXPORT ClapInstance final : public QObject
auto controlCount() const -> std::size_t;
auto hasNoteInput() const -> bool;

/////////////////////////////////////////
// Instance
/////////////////////////////////////////

//! Destroy the plugin instance
void destroy();
/**
* Info
*/

auto isValid() const -> bool;

auto host() const -> const clap_host* { return &m_host; };
auto plugin() const -> const clap_plugin* { return m_plugin; }
auto info() const -> const ClapPluginInfo& { return m_pluginInfo; }

/////////////////////////////////////////
// Extensions
/////////////////////////////////////////

auto audioPorts() -> ClapAudioPorts& { return m_audioPorts; }
auto gui() -> ClapGui& { return m_gui; }
auto logger() const -> const ClapLog& { return m_log; }
auto notePorts() -> ClapNotePorts& { return m_notePorts; }
auto params() -> ClapParams& { return m_params; }
auto state() -> ClapState& { return m_state; }
auto timerSupport() -> ClapTimerSupport& { return m_timerSupport; }

/////////////////////////////////////////
// Host
/////////////////////////////////////////

//! Executes idle tasks
void idle();

/////////////////////////////////////////
// Plugin
/////////////////////////////////////////
/**
* Control
*/

auto start() -> bool; //!< Loads, inits, and activates in that order
auto restart() -> bool;
void destroy();

auto load() -> bool;
auto unload() -> bool;
auto init() -> bool;
auto activate() -> bool;
auto deactivate() -> bool;

void idle();

auto processBegin(std::uint32_t frames) -> bool;
void processNote(f_cnt_t offset, std::int8_t channel, std::int16_t key, std::uint8_t velocity, bool isOn);
void processKeyPressure(f_cnt_t offset, std::int8_t channel, std::int16_t key, std::uint8_t pressure);
Expand All @@ -181,77 +163,100 @@ class LMMS_EXPORT ClapInstance final : public QObject
auto isSleeping() const -> bool;
auto isErrorState() const -> bool;

/**
* Extensions
*/

auto host() const -> const clap_host* { return &m_host; };
auto plugin() const -> const clap_plugin* { return m_plugin; }

auto audioPorts() -> ClapAudioPorts& { return m_audioPorts; }
auto gui() -> ClapGui& { return m_gui; }
auto logger() const -> const ClapLog& { return m_log; }
auto notePorts() -> ClapNotePorts& { return m_notePorts; }
auto params() -> ClapParams& { return m_params; }
auto state() -> ClapState& { return m_state; }
auto timerSupport() -> ClapTimerSupport& { return m_timerSupport; }

private:
/**
* State
*/

/////////////////////////////////////////
// Host API implementation
/////////////////////////////////////////
void setPluginState(PluginState state);
auto isNextStateValid(PluginState next) const -> bool;

void setHost();
clap_host m_host;
template<typename... Args>
auto isCurrentStateValid(Args... validStates) const -> bool
{
return ((m_pluginState == validStates) || ...);
}

/**
* Host API implementation
*/

static auto clapGetExtension(const clap_host* host, const char* extensionId) -> const void*;
static void clapRequestCallback(const clap_host* host);
static void clapRequestProcess(const clap_host* host);
static void clapRequestRestart(const clap_host* host);
static void clapLatencyChanged(const clap_host* host);

/////////////////////////////////////////
// Plugin
/////////////////////////////////////////

template<typename... Args>
void checkPluginStateCurrent(Args... possibilities);
/**
* Latency extension
* TODO: Fully implement and move to separate class
*/

auto isPluginNextStateValid(PluginState next) -> bool;
void setPluginState(PluginState state);
static void clapLatencyChanged(const clap_host* host);
static constexpr const clap_host_latency s_clapLatency {
&clapLatencyChanged
};

template<typename T, class F>
auto pluginExtensionInit(const T*& ext, const char* id, F* checkFunc) -> bool;
/**
* Important data members
*/

const clap_plugin* m_plugin = nullptr;
ClapPluginInfo m_pluginInfo;
PluginState m_pluginState = PluginState::None;

PluginState m_pluginState = PluginState::Inactive;

std::vector<PluginIssue> m_pluginIssues;

std::int64_t m_steadyTime = 0;
clap_host m_host;
const clap_plugin* m_plugin = nullptr;

/**
* Process-related
*/

clap_process m_process{};
clap::helpers::EventList m_evIn; // TODO: Find better way to handle param and note events
clap::helpers::EventList m_evOut; // TODO: Find better way to handle param and note events
clap_process m_process{};

/**
* MIDI
*/
*/

// many things here may be moved into the `Instrument` class
static constexpr std::size_t s_maxMidiInputEvents = 1024;

//! Spinlock for the MIDI ringbuffer (for MIDI events going to the plugin)
std::atomic_flag m_ringLock = ATOMIC_FLAG_INIT;

//! MIDI ringbuffer (for MIDI events going to the plugin)
ringbuffer_t<struct MidiInputEvent> m_midiInputBuf;

//! MIDI ringbuffer reader
ringbuffer_reader_t<struct MidiInputEvent> m_midiInputReader;

/**
* Scheduling
*/

bool m_scheduleRestart = false;
bool m_scheduleDeactivate = false;
bool m_scheduleProcess = true; // TODO: ???
bool m_scheduleProcess = true;
bool m_scheduleMainThreadCallback = false;

/**
* Extensions
*/
static constexpr const clap_host_latency s_clapLatency {
&clapLatencyChanged
};

ClapAudioPorts m_audioPorts{ this };
ClapGui m_gui{ this };
Expand Down
8 changes: 7 additions & 1 deletion include/ClapParameter.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ class ClapParameter : public QObject
return std::clamp(m_value + m_modulation, m_info.min_value, m_info.max_value);
}

auto isValueValid(const double v) const -> bool;
auto isValueValid(const double v) const -> bool
{
return m_info.min_value <= v && v <= m_info.max_value;
}

auto getShortInfoString() const -> std::string;
auto getInfoString() const -> std::string;
Expand All @@ -89,17 +92,20 @@ class ClapParameter : public QObject
auto info() const noexcept -> const clap_param_info& { return m_info; }

auto isBeingAdjusted() const noexcept -> bool { return m_isBeingAdjusted; }

void setIsAdjusting(bool isAdjusting)
{
if (isAdjusting && !m_isBeingAdjusted) { beginAdjust(); }
else if (!isAdjusting && m_isBeingAdjusted) { endAdjust(); }
}

void beginAdjust()
{
Q_ASSERT(!m_isBeingAdjusted);
m_isBeingAdjusted = true;
emit isBeingAdjustedChanged();
}

void endAdjust()
{
Q_ASSERT(m_isBeingAdjusted);
Expand Down
2 changes: 1 addition & 1 deletion src/core/Track.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ Track * Track::create( const QDomElement & element, TrackContainer * tc )
Track* Track::clone()
{
// Save track to temporary XML and load it to create a new identical track
QDomDocument doc;
QDomDocument doc{"clonedtrack"};
QDomElement parent = doc.createElement("clonedtrack");
saveState(doc, parent);
Track* t = create(parent.firstChild().toElement(), m_trackContainer);
Expand Down
Loading