commit bb238cbc782299fa9db88e637d504f648bdcd22f
parent 8e72ff666e92754c77c7f5651bc5435748ce8897
Author: Alexandre BIQUE <bique.alexandre@gmail.com>
Date: Wed, 23 Jun 2021 19:11:07 +0200
More work on examples
Diffstat:
15 files changed, 202 insertions(+), 30 deletions(-)
diff --git a/examples/glue/clap-plugin.cc b/examples/glue/clap-plugin.cc
@@ -283,13 +283,6 @@ namespace clap {
return self.stateLoad(stream);
}
- bool Plugin::clapStateIsDirty(const clap_plugin *plugin) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_state.is_dirty");
-
- return self.stateIsDirty();
- }
-
//-------------------------//
// clap_plugin_preset_load //
//-------------------------//
diff --git a/examples/glue/clap-plugin.hh b/examples/glue/clap-plugin.hh
@@ -66,7 +66,6 @@ namespace clap {
virtual bool implementsState() const noexcept { return false; }
virtual bool stateSave(clap_ostream *stream) noexcept { return false; }
virtual bool stateLoad(clap_istream *stream) noexcept { return false; }
- virtual bool stateIsDirty() const noexcept { return false; }
void stateMarkDirty() const noexcept {
if (canUseState())
hostState_->mark_dirty(host_);
@@ -274,7 +273,6 @@ namespace clap {
// clap_plugin_state
static bool clapStateSave(const clap_plugin *plugin, clap_ostream *stream) noexcept;
static bool clapStateLoad(const clap_plugin *plugin, clap_istream *stream) noexcept;
- static bool clapStateIsDirty(const clap_plugin *plugin) noexcept;
// clap_plugin_preset
static bool clapPresetLoadFromFile(const clap_plugin *plugin, const char *path) noexcept;
@@ -362,7 +360,6 @@ namespace clap {
static const constexpr clap_plugin_state pluginState_ = {
clapStateSave,
clapStateLoad,
- clapStateIsDirty,
};
static const constexpr clap_plugin_preset_load pluginPresetLoad_ = {
diff --git a/examples/gui/CMakeLists.txt b/examples/gui/CMakeLists.txt
@@ -3,9 +3,14 @@ set(CMAKE_AUTOMOC ON)
find_package(Qt6Core REQUIRED)
find_package(Qt6Widgets REQUIRED)
+find_package(Qt6Qml REQUIRED)
add_executable(clap-gui
main.cc
+
+ application.hh
+ application.cc
)
+target_link_libraries(clap-gui Qt6::Qml Qt6::Widgets Qt6::Core)
-set_target_properties(clap-gui PROPERTIES CXX_STANDARD 20)
-\ No newline at end of file
+set_target_properties(clap-gui PROPERTIES CXX_STANDARD 17)
+\ No newline at end of file
diff --git a/examples/gui/application.cc b/examples/gui/application.cc
@@ -0,0 +1,23 @@
+#include <QCommandLineParser>
+#include <QQmlApplicationEngine>
+
+#include "application.hh"
+
+Application::Application(int argc, char **argv)
+ : QGuiApplication(argc, argv), qmlEngine_(new QQmlApplicationEngine(this)) {
+
+ QCommandLineParser parser;
+
+ QCommandLineOption qmlOpt("qml", tr("path to the QML skin"), tr("path"));
+ QCommandLineOption socketOpt("socket", tr("path to the QML skin"), tr("path"));
+
+ parser.addOption(qmlOpt);
+ parser.addOption(socketOpt);
+ parser.addHelpOption();
+
+ parser.process(*this);
+
+ qmlEngine_->load(parser.value(qmlOpt));
+ if (qmlEngine_->rootObjects().empty())
+ throw std::invalid_argument("bad qml file");
+}
diff --git a/examples/gui/application.hh b/examples/gui/application.hh
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <QGuiApplication>
+
+class QQmlApplicationEngine;
+
+class Application : public QGuiApplication {
+ Q_OBJECT;
+
+public:
+ Application(int argc, char **argv);
+
+private:
+ QQmlApplicationEngine *qmlEngine_ = nullptr;
+};
+\ No newline at end of file
diff --git a/examples/gui/main.cc b/examples/gui/main.cc
@@ -1,4 +1,7 @@
-int main(int argc, char **argv)
-{
- return 0;
+#include "application.hh"
+
+int main(int argc, char **argv) {
+ Application app(argc, argv);
+
+ return app.exec();
}
\ No newline at end of file
diff --git a/examples/host/application.cc b/examples/host/application.cc
@@ -22,10 +22,10 @@ Application::Application(int argc, char **argv)
assert(!instance_);
instance_ = this;
- QApplication::setOrganizationDomain("u-he.com");
- QApplication::setOrganizationName("u-he");
- QApplication::setApplicationName("uhost");
- QApplication::setApplicationVersion("1.0");
+ setOrganizationDomain("u-he.com");
+ setOrganizationName("u-he");
+ setApplicationName("uhost");
+ setApplicationVersion("1.0");
parseCommandLine();
diff --git a/examples/host/plugin-host.cc b/examples/host/plugin-host.cc
@@ -53,7 +53,7 @@ PluginHost::PluginHost(Engine &engine) : QObject(&engine), engine_(engine) {
hostQuickControls_.pages_changed = PluginHost::clapQuickControlsPagesChanged;
hostQuickControls_.selected_page_changed = PluginHost::clapQuickControlsSelectedPageChanged;
- hostState_.mark_dirty = PluginHost::clapMarkSetDirty;
+ hostState_.mark_dirty = PluginHost::clapStateMarkDirty;
initThreadPool();
}
@@ -977,7 +977,7 @@ bool PluginHost::loadNativePluginPreset(const std::string &path) {
return pluginPresetLoad_->from_file(plugin_, path.c_str());
}
-void PluginHost::clapMarkSetDirty(const clap_host *host) {
+void PluginHost::clapStateMarkDirty(const clap_host *host) {
checkForMainThread();
auto h = fromHost(host);
@@ -986,7 +986,7 @@ void PluginHost::clapMarkSetDirty(const clap_host *host) {
throw std::logic_error("Plugin called clap_host_state.set_dirty() but the host does not "
"provide a complete clap_plugin_state interface.");
- // TODO set dirty
+ h->stateIsDirty_ = true;
}
void PluginHost::setPluginState(PluginState state) {
diff --git a/examples/host/plugin-host.hh b/examples/host/plugin-host.hh
@@ -117,7 +117,7 @@ private:
/* clap host gui callbacks */
static bool clapGuiResize(const clap_host *host, int32_t width, int32_t height);
- static void clapMarkSetDirty(const clap_host *host);
+ static void clapStateMarkDirty(const clap_host *host);
private:
Engine &engine_;
@@ -213,6 +213,7 @@ private:
void setPluginState(PluginState state);
PluginState state_ = Inactive;
+ bool stateIsDirty_ = false;
bool scheduleDeactivateForParameterScan_ = false;
uint32_t scheduleParamsRescanFlags_ = 0;
};
diff --git a/examples/plugins/CMakeLists.txt b/examples/plugins/CMakeLists.txt
@@ -1,3 +1,5 @@
+find_package(Boost REQUIRED COMPONENTS serialization iostreams)
+
add_library(
clap-plugins SHARED
clap-entry.cc
@@ -6,9 +8,10 @@ add_library(
parameter-interpolator.hh
plugin-helper.cc
plugin-helper.hh
+ stream-helper.hh
dc-offset/dc-offset.hh
dc-offset/dc-offset.cc
gain/gain.hh
gain/gain.cc)
-target_link_libraries(clap-plugins clap-plugin-glue)
+target_link_libraries(clap-plugins clap-plugin-glue Boost::serialization Boost::iostreams)
set_target_properties(clap-plugins PROPERTIES CXX_STANDARD 20)
diff --git a/examples/plugins/clap-entry.cc b/examples/plugins/clap-entry.cc
@@ -7,6 +7,7 @@
#include <vector>
#include "gain/gain.hh"
+#include "dc-offset/dc-offset.hh"
struct PluginEntry {
using create_func = std::function<const clap_plugin *(const clap_host *)>;
@@ -30,6 +31,7 @@ static void addPlugin() {
static bool clap_init(const char *plugin_path) {
addPlugin<clap::Gain>();
+ addPlugin<clap::DcOffset>();
return true;
}
diff --git a/examples/plugins/parameters.hh b/examples/plugins/parameters.hh
@@ -3,6 +3,12 @@
#include <unordered_map>
#include <vector>
+#include <boost/serialization/serialization.hpp>
+#include <boost/serialization/split_member.hpp>
+#include <boost/serialization/version.hpp>
+#include <boost/serialization/vector.hpp>
+#include <boost/serialization/utility.hpp>
+
#include <clap/all.h>
#include "parameter-interpolator.hh"
@@ -17,6 +23,10 @@ namespace clap {
const double modulatedValue() const noexcept { return value_ + modulation_; }
const clap_param_info &info() const noexcept { return info_; }
+ void setDefaultValue() {
+ setValue(info_.default_value, 0);
+ }
+
void setValue(double val, double mod) {
value_ = val;
modulation_ = mod;
@@ -56,6 +66,16 @@ namespace clap {
}
private:
+ friend class boost::serialization::access;
+ // When the class Archive corresponds to an output archive, the
+ // & operator is defined similar to <<. Likewise, when the class Archive
+ // is a type of input archive the & operator is defined similar to >>.
+ template <class Archive>
+ void serialize(Archive &ar, const unsigned int version) {
+ ar &info_.id;
+ ar &value_;
+ }
+
clap_param_info info_;
double value_;
@@ -83,7 +103,40 @@ namespace clap {
Parameter *getById(clap_id id) const noexcept;
private:
+ friend class boost::serialization::access;
+
+ template <class Archive>
+ void save(Archive &ar, const unsigned int version) const {
+ std::vector<std::pair<clap_id, double>> values;
+ for (auto &p : params_)
+ values.emplace_back(p->info().id, p->value());
+
+ ar << values;
+ }
+
+ template <class Archive>
+ void load(Archive &ar, const unsigned int version) {
+ std::vector<std::pair<clap_id, double>> values;
+ ar >> values;
+
+ for (auto & p : params_)
+ p->setDefaultValue();
+
+ for (auto &v : values)
+ {
+ auto *p = getById(v.first);
+ if (!p)
+ continue;
+ p->setValue(v.second, 0);
+ }
+ }
+
+ BOOST_SERIALIZATION_SPLIT_MEMBER()
+
std::vector<std::unique_ptr<Parameter>> params_;
std::unordered_map<clap_id, Parameter *> id2param_;
};
-} // namespace clap
-\ No newline at end of file
+
+} // namespace clap
+
+BOOST_CLASS_VERSION(clap::Parameters, 1)
+\ No newline at end of file
diff --git a/examples/plugins/plugin-helper.cc b/examples/plugins/plugin-helper.cc
@@ -1,4 +1,8 @@
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/archive/text_oarchive.hpp>
+
#include "plugin-helper.hh"
+#include "stream-helper.hh"
namespace clap {
@@ -53,4 +57,26 @@ namespace clap {
}
bool PluginHelper::audioPortsSetConfig(clap_id config_id) noexcept { return false; }
+
+ bool PluginHelper::stateSave(clap_ostream *stream) noexcept {
+ try {
+ OStream os(stream);
+ boost::archive::text_oarchive ar(os);
+ ar << parameters_;
+ } catch (...) {
+ return false;
+ }
+ return true;
+ }
+
+ bool PluginHelper::stateLoad(clap_istream *stream) noexcept {
+ try {
+ IStream is(stream);
+ boost::archive::text_iarchive ar(is);
+ ar >> parameters_;
+ } catch (...) {
+ return false;
+ }
+ return true;
+ }
} // namespace clap
\ No newline at end of file
diff --git a/examples/plugins/plugin-helper.hh b/examples/plugins/plugin-helper.hh
@@ -10,15 +10,21 @@ namespace clap {
PluginHelper(const clap_plugin_descriptor *desc, const clap_host *host);
protected:
- // clap_plugin
+ //-------------//
+ // clap_plugin //
+ //-------------//
bool init() noexcept override;
void initTrackInfo() noexcept;
- // clap_plugin_track_info
+ //------------------------//
+ // clap_plugin_track_info //
+ //------------------------//
bool implementsTrackInfo() const noexcept override { return true; }
void trackInfoChanged() noexcept override;
- // clap_plugin_audio_ports
+ //-------------------------//
+ // clap_plugin_audio_ports //
+ //-------------------------//
bool implementsAudioPorts() const noexcept override;
uint32_t audioPortsCount(bool is_input) const noexcept override;
bool audioPortsInfo(uint32_t index,
@@ -29,7 +35,9 @@ namespace clap {
clap_audio_ports_config *config) const noexcept override;
bool audioPortsSetConfig(clap_id config_id) noexcept override;
- // clap_plugin_params
+ //--------------------//
+ // clap_plugin_params //
+ //--------------------//
bool implementsParams() const noexcept override { return true; }
uint32_t paramsCount() const noexcept override { return parameters_.count(); }
@@ -59,6 +67,13 @@ namespace clap {
return false;
}
+ //-------------------//
+ // clap_plugin_state //
+ //-------------------//
+ bool implementsState() const noexcept override { return true; }
+ bool stateSave(clap_ostream *stream) noexcept override;
+ bool stateLoad(clap_istream *stream) noexcept override;
+
//////////////////////
// Cached Host Info //
//////////////////////
diff --git a/examples/plugins/stream-helper.hh b/examples/plugins/stream-helper.hh
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <boost/iostreams/concepts.hpp>
+#include <boost/iostreams/stream.hpp>
+
+#include <clap/stream.h>
+
+namespace clap {
+ class Source : public boost::iostreams::source {
+ public:
+ explicit Source(clap_istream *is) : is_(is) {}
+
+ std::streamsize read(char *s, std::streamsize n) noexcept { return is_->read(is_, s, n); }
+
+ private:
+ clap_istream *is_;
+ };
+
+ using IStream = boost::iostreams::stream<Source>;
+
+ class Sink : public boost::iostreams::sink {
+ public:
+ explicit Sink(clap_ostream *os) : os_(os) {}
+
+ std::streamsize write(const char *s, std::streamsize n) noexcept {
+ return os_->write(os_, s, n);
+ }
+
+ private:
+ clap_ostream *os_;
+ };
+
+ using OStream = boost::iostreams::stream<Sink>;
+} // namespace clap
+\ No newline at end of file