diff options
Diffstat (limited to 'include/ingen/client')
-rw-r--r-- | include/ingen/client/ArcModel.hpp | 65 | ||||
-rw-r--r-- | include/ingen/client/BlockModel.hpp | 124 | ||||
-rw-r--r-- | include/ingen/client/ClientStore.hpp | 130 | ||||
-rw-r--r-- | include/ingen/client/GraphModel.hpp | 89 | ||||
-rw-r--r-- | include/ingen/client/ObjectModel.hpp | 100 | ||||
-rw-r--r-- | include/ingen/client/PluginModel.hpp | 133 | ||||
-rw-r--r-- | include/ingen/client/PluginUI.hpp | 119 | ||||
-rw-r--r-- | include/ingen/client/PortModel.hpp | 101 | ||||
-rw-r--r-- | include/ingen/client/SigClientInterface.hpp | 59 | ||||
-rw-r--r-- | include/ingen/client/SocketClient.hpp | 92 | ||||
-rw-r--r-- | include/ingen/client/client.h | 31 | ||||
-rw-r--r-- | include/ingen/client/signal.hpp | 34 |
12 files changed, 1077 insertions, 0 deletions
diff --git a/include/ingen/client/ArcModel.hpp b/include/ingen/client/ArcModel.hpp new file mode 100644 index 00000000..8104b188 --- /dev/null +++ b/include/ingen/client/ArcModel.hpp @@ -0,0 +1,65 @@ +/* + This file is part of Ingen. + Copyright 2007-2015 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INGEN_CLIENT_ARCMODEL_HPP +#define INGEN_CLIENT_ARCMODEL_HPP + +#include "ingen/Arc.hpp" +#include "ingen/client/PortModel.hpp" +#include "ingen/ingen.h" +#include "raul/Path.hpp" + +#include <cassert> +#include <memory> +#include <string> +#include <utility> + +namespace ingen::client { + +/** Class to represent a port->port connections in the engine. + * + * @ingroup IngenClient + */ +class INGEN_API ArcModel : public Arc +{ +public: + std::shared_ptr<PortModel> tail() const { return _tail; } + std::shared_ptr<PortModel> head() const { return _head; } + + const raul::Path& tail_path() const override { return _tail->path(); } + const raul::Path& head_path() const override { return _head->path(); } + +private: + friend class ClientStore; + + ArcModel(std::shared_ptr<PortModel> tail, std::shared_ptr<PortModel> head) + : _tail(std::move(tail)) + , _head(std::move(head)) + { + assert(_tail); + assert(_head); + assert(_tail->parent()); + assert(_head->parent()); + assert(_tail->path() != _head->path()); + } + + const std::shared_ptr<PortModel> _tail; + const std::shared_ptr<PortModel> _head; +}; + +} // namespace ingen::client + +#endif // INGEN_CLIENT_ARCMODEL_HPP diff --git a/include/ingen/client/BlockModel.hpp b/include/ingen/client/BlockModel.hpp new file mode 100644 index 00000000..d2641f77 --- /dev/null +++ b/include/ingen/client/BlockModel.hpp @@ -0,0 +1,124 @@ +/* + This file is part of Ingen. + Copyright 2007-2015 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INGEN_CLIENT_BLOCKMODEL_HPP +#define INGEN_CLIENT_BLOCKMODEL_HPP + +#include "ingen/Node.hpp" +#include "ingen/URI.hpp" +#include "ingen/client/ObjectModel.hpp" +#include "ingen/client/PluginModel.hpp" // IWYU pragma: keep +#include "ingen/client/signal.hpp" +#include "ingen/ingen.h" + +#include <cstdint> +#include <memory> +#include <string> +#include <vector> + +// IWYU pragma: no_include <algorithm> + +namespace raul { +class Path; +class Symbol; +} // namespace raul + +namespace ingen { + +class Resource; +class URIs; + +namespace client { + +class PortModel; + +/** Block model class, used by the client to store engine's state. + * + * @ingroup IngenClient + */ +class INGEN_API BlockModel : public ObjectModel +{ +public: + BlockModel(const BlockModel& copy); + ~BlockModel() override; + + GraphType graph_type() const override { return Node::GraphType::BLOCK; } + + using Ports = std::vector<std::shared_ptr<const PortModel>>; + + std::shared_ptr<const PortModel> get_port(const raul::Symbol& symbol) const; + std::shared_ptr<const PortModel> get_port(uint32_t index) const; + + Node* port(uint32_t index) const override; + + const URI& plugin_uri() const { return _plugin_uri; } + const Resource* plugin() const override { return _plugin.get(); } + Resource* plugin() { return _plugin.get(); } + std::shared_ptr<PluginModel> plugin_model() const { return _plugin; } + uint32_t num_ports() const override { return _ports.size(); } + const Ports& ports() const { return _ports; } + + void default_port_value_range(const std::shared_ptr<const PortModel>& port, + float& min, + float& max, + uint32_t srate = 1) const; + + void port_value_range(const std::shared_ptr<const PortModel>& port, + float& min, + float& max, + uint32_t srate = 1) const; + + std::string label() const; + std::string port_label(const std::shared_ptr<const PortModel>& port) const; + + // Signals + INGEN_SIGNAL(new_port, void, std::shared_ptr<const PortModel>) + INGEN_SIGNAL(removed_port, void, std::shared_ptr<const PortModel>) + +protected: + friend class ClientStore; + + BlockModel(URIs& uris, URI plugin_uri, const raul::Path& path); + + BlockModel(URIs& uris, + const std::shared_ptr<PluginModel>& plugin, + const raul::Path& path); + + explicit BlockModel(const raul::Path& path); + + void add_child(const std::shared_ptr<ObjectModel>& c) override; + bool remove_child(const std::shared_ptr<ObjectModel>& c) override; + void add_port(const std::shared_ptr<PortModel>& pm); + void remove_port(const std::shared_ptr<PortModel>& port); + void remove_port(const raul::Path& port_path); + void set(const std::shared_ptr<ObjectModel>& model) override; + + virtual void clear(); + + Ports _ports; ///< Vector of ports + URI _plugin_uri; ///< Plugin URI (if PluginModel is unknown) + std::shared_ptr<PluginModel> _plugin; ///< Plugin this is an instance of + +private: + mutable uint32_t _num_values; ///< Size of _min_values and _max_values + mutable float* _min_values; ///< Port min values (cached for LV2) + mutable float* _max_values; ///< Port max values (cached for LV2) +}; + +} // namespace client +} // namespace ingen + +#endif // INGEN_CLIENT_BLOCKMODEL_HPP diff --git a/include/ingen/client/ClientStore.hpp b/include/ingen/client/ClientStore.hpp new file mode 100644 index 00000000..83cce726 --- /dev/null +++ b/include/ingen/client/ClientStore.hpp @@ -0,0 +1,130 @@ +/* + This file is part of Ingen. + Copyright 2007-2016 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INGEN_CLIENT_CLIENTSTORE_HPP +#define INGEN_CLIENT_CLIENTSTORE_HPP + +#include "ingen/Interface.hpp" +#include "ingen/Message.hpp" +#include "ingen/Store.hpp" +#include "ingen/URI.hpp" +#include "ingen/client/signal.hpp" +#include "ingen/ingen.h" + +#include <map> +#include <memory> +#include <utility> + +namespace raul { +class Path; +} // namespace raul + +namespace ingen { + +class Atom; +class Log; +class Resource; +class URIs; + +namespace client { + +class GraphModel; +class ObjectModel; +class PluginModel; +class SigClientInterface; + +/** Automatically manages models of objects in the engine. + * + * @ingroup IngenClient + */ +class INGEN_API ClientStore : public Store + , public Interface + , public INGEN_TRACKABLE { +public: + ClientStore(URIs& uris, + Log& log, + const std::shared_ptr<SigClientInterface>& emitter = + std::shared_ptr<SigClientInterface>()); + + URI uri() const override { return URI("ingen:/clients/store"); } + + std::shared_ptr<const ObjectModel> object(const raul::Path& path) const; + std::shared_ptr<const PluginModel> plugin(const URI& uri) const; + std::shared_ptr<const Resource> resource(const URI& uri) const; + + void clear(); + + using Plugins = std::map<const URI, std::shared_ptr<PluginModel>>; + + std::shared_ptr<const Plugins> plugins() const { return _plugins; } + std::shared_ptr<Plugins> plugins() { return _plugins; } + + void set_plugins(std::shared_ptr<Plugins> p) { _plugins = std::move(p); } + + URIs& uris() { return _uris; } + + void message(const Message& msg) override; + + void operator()(const BundleBegin&) noexcept {} + void operator()(const BundleEnd&) noexcept {} + void operator()(const Connect&); + void operator()(const Copy&); + void operator()(const Del&); + void operator()(const Delta&); + void operator()(const Disconnect&); + void operator()(const DisconnectAll&); + void operator()(const Error&) noexcept {} + void operator()(const Get&) noexcept {} + void operator()(const Move&); + void operator()(const Put&); + void operator()(const Redo&) noexcept {} + void operator()(const Response&) noexcept {} + void operator()(const SetProperty&); + void operator()(const Undo&) noexcept {} + + INGEN_SIGNAL(new_object, void, std::shared_ptr<ObjectModel>) + INGEN_SIGNAL(new_plugin, void, std::shared_ptr<PluginModel>) + INGEN_SIGNAL(plugin_deleted, void, URI) + +private: + std::shared_ptr<ObjectModel> _object(const raul::Path& path); + std::shared_ptr<PluginModel> _plugin(const URI& uri); + std::shared_ptr<PluginModel> _plugin(const Atom& uri); + std::shared_ptr<Resource> _resource(const URI& uri); + + void add_object(const std::shared_ptr<ObjectModel>& object); + std::shared_ptr<ObjectModel> remove_object(const raul::Path& path); + + void add_plugin(const std::shared_ptr<PluginModel>& pm); + + std::shared_ptr<GraphModel> connection_graph(const raul::Path& tail_path, + const raul::Path& head_path); + + // Slots for SigClientInterface signals + bool attempt_connection(const raul::Path& tail_path, + const raul::Path& head_path); + + URIs& _uris; + Log& _log; + std::shared_ptr<SigClientInterface> _emitter; + + std::shared_ptr<Plugins> _plugins; ///< Map, keyed by plugin URI +}; + +} // namespace client +} // namespace ingen + +#endif // INGEN_CLIENT_CLIENTSTORE_HPP diff --git a/include/ingen/client/GraphModel.hpp b/include/ingen/client/GraphModel.hpp new file mode 100644 index 00000000..0ae756d8 --- /dev/null +++ b/include/ingen/client/GraphModel.hpp @@ -0,0 +1,89 @@ +/* + This file is part of Ingen. + Copyright 2007-2015 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INGEN_CLIENT_GRAPHMODEL_HPP +#define INGEN_CLIENT_GRAPHMODEL_HPP + +#include "ingen/Node.hpp" +#include "ingen/URIs.hpp" +#include "ingen/client/BlockModel.hpp" +#include "ingen/client/signal.hpp" +#include "ingen/ingen.h" + +#include <cstdint> +#include <memory> + +namespace raul { +class Path; +} // namespace raul + +namespace ingen { + +class URI; + +namespace client { + +class ArcModel; +class ObjectModel; +class PortModel; + +/** Client's model of a graph. + * + * @ingroup IngenClient + */ +class INGEN_API GraphModel : public BlockModel +{ +public: + /* WARNING: Copy constructor creates a shallow copy WRT connections */ + + GraphType graph_type() const override { return Node::GraphType::GRAPH; } + + std::shared_ptr<ArcModel> + get_arc(const ingen::Node* tail, const ingen::Node* head); + + bool enabled() const; + bool polyphonic() const; + uint32_t internal_poly() const; + + // Signals + INGEN_SIGNAL(new_block, void, std::shared_ptr<BlockModel>) + INGEN_SIGNAL(removed_block, void, std::shared_ptr<BlockModel>) + INGEN_SIGNAL(new_arc, void, std::shared_ptr<ArcModel>) + INGEN_SIGNAL(removed_arc, void, std::shared_ptr<ArcModel>) + +private: + friend class ClientStore; + + GraphModel(URIs& uris, const raul::Path& graph_path) + : BlockModel(uris, + static_cast<const URI&>(uris.ingen_Graph), + graph_path) + {} + + void clear() override; + void add_child(const std::shared_ptr<ObjectModel>& c) override; + bool remove_child(const std::shared_ptr<ObjectModel>& o) override; + void remove_arcs_on(const std::shared_ptr<PortModel>& p); + + void add_arc(const std::shared_ptr<ArcModel>& arc); + void remove_arc(const ingen::Node* tail, + const ingen::Node* head); +}; + +} // namespace client +} // namespace ingen + +#endif // INGEN_CLIENT_GRAPHMODEL_HPP diff --git a/include/ingen/client/ObjectModel.hpp b/include/ingen/client/ObjectModel.hpp new file mode 100644 index 00000000..e92618f8 --- /dev/null +++ b/include/ingen/client/ObjectModel.hpp @@ -0,0 +1,100 @@ +/* + This file is part of Ingen. + Copyright 2007-2015 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +/** + @defgroup IngenClient Client-Side Models and Utilities +*/ + +#ifndef INGEN_CLIENT_OBJECTMODEL_HPP +#define INGEN_CLIENT_OBJECTMODEL_HPP + +#include "ingen/Node.hpp" +#include "ingen/URI.hpp" +#include "ingen/URIs.hpp" +#include "ingen/client/signal.hpp" +#include "ingen/ingen.h" +#include "raul/Path.hpp" +#include "raul/Symbol.hpp" + +#include <memory> + +namespace ingen { + +class Atom; + +namespace client { + +/** Base class for all Node models (BlockModel, GraphModel, PortModel). + * + * There are no non-const public methods intentionally, models are not allowed + * to be manipulated directly by anything (but the Store) because of the + * asynchronous nature of engine control. To change something, use the + * controller (which the model probably shouldn't have a reference to but oh + * well, it reduces Collection Hell) and wait for the result (as a signal + * from this Model). + * + * @ingroup IngenClient + */ +class INGEN_API ObjectModel : public Node +{ +public: + bool is_a(const URIs::Quark& type) const; + + const Atom& get_property(const URI& key) const override; + + void on_property(const URI& uri, const Atom& value) override; + void on_property_removed(const URI& uri, const Atom& value) override; + + const raul::Path& path() const override { return _path; } + const raul::Symbol& symbol() const override { return _symbol; } + + std::shared_ptr<ObjectModel> parent() const { return _parent; } + bool polyphonic() const; + + Node* graph_parent() const override { return _parent.get(); } + + // Signals + INGEN_SIGNAL(new_child, void, std::shared_ptr<ObjectModel>) + INGEN_SIGNAL(removed_child, void, std::shared_ptr<ObjectModel>) + INGEN_SIGNAL(property, void, const URI&, const Atom&) + INGEN_SIGNAL(property_removed, void, const URI&, const Atom&) + INGEN_SIGNAL(destroyed, void) + INGEN_SIGNAL(moved, void) + +protected: + friend class ClientStore; + + ObjectModel(URIs& uris, const raul::Path& path); + ObjectModel(const ObjectModel& copy); + + void set_path(const raul::Path& p) override; + virtual void set_parent(const std::shared_ptr<ObjectModel>& p); + virtual void add_child(const std::shared_ptr<ObjectModel>& c) {} + virtual bool remove_child(const std::shared_ptr<ObjectModel>& c) { return true; } + + virtual void set(const std::shared_ptr<ObjectModel>& o); + + std::shared_ptr<ObjectModel> _parent; + +private: + raul::Path _path; + raul::Symbol _symbol; +}; + +} // namespace client +} // namespace ingen + +#endif // INGEN_CLIENT_OBJECTMODEL_HPP diff --git a/include/ingen/client/PluginModel.hpp b/include/ingen/client/PluginModel.hpp new file mode 100644 index 00000000..7f86f680 --- /dev/null +++ b/include/ingen/client/PluginModel.hpp @@ -0,0 +1,133 @@ +/* + This file is part of Ingen. + Copyright 2007-2017 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INGEN_CLIENT_PLUGINMODEL_HPP +#define INGEN_CLIENT_PLUGINMODEL_HPP + +#include "ingen/Atom.hpp" +#include "ingen/Forge.hpp" +#include "ingen/Properties.hpp" +#include "ingen/Resource.hpp" +#include "ingen/URI.hpp" +#include "ingen/URIs.hpp" +#include "ingen/client/signal.hpp" +#include "ingen/ingen.h" +#include "lilv/lilv.h" +#include "raul/Symbol.hpp" + +#include <cstdint> +#include <map> +#include <memory> +#include <string> + +namespace Sord { +class World; +} // namespace Sord + +namespace ingen { + +class World; + +namespace client { + +class BlockModel; +class PluginUI; + +/** Model for a plugin available for loading. + * + * @ingroup IngenClient + */ +class INGEN_API PluginModel : public ingen::Resource +{ +public: + PluginModel(URIs& uris, + const URI& uri, + const Atom& type, + const ingen::Properties& properties); + + const Atom& type() const { return _type; } + + URI type_uri() const + { + return URI(_type.is_valid() ? _uris.forge.str(_type, false) + : "http://www.w3.org/2002/07/owl#Nothing"); + } + + const Atom& get_property(const URI& key) const override; + + raul::Symbol default_block_symbol() const; + std::string human_name() const; + std::string port_human_name(uint32_t index) const; + + using ScalePoints = std::map<float, std::string>; + ScalePoints port_scale_points(uint32_t index) const; + + using Presets = std::map<URI, std::string>; + const Presets& presets() const { return _presets; } + + static LilvWorld* lilv_world() { return _lilv_world; } + const LilvPlugin* lilv_plugin() const { return _lilv_plugin; } + + const LilvPort* lilv_port(uint32_t index) const; + + static void set_lilv_world(LilvWorld* world); + + bool has_ui() const; + + std::shared_ptr<PluginUI> + ui(ingen::World& world, + const std::shared_ptr<const BlockModel>& block) const; + + std::string documentation(bool html) const; + std::string port_documentation(uint32_t index, bool html) const; + + static void set_rdf_world(Sord::World& world) { + _rdf_world = &world; + } + + static Sord::World* rdf_world() { return _rdf_world; } + + // Signals + INGEN_SIGNAL(changed, void) + INGEN_SIGNAL(property, void, const URI&, const Atom&) + INGEN_SIGNAL(preset, void, const URI&, const std::string&) + + bool fetched() const { return _fetched; } + void set_fetched(bool f) { _fetched = f; } + +protected: + friend class ClientStore; + void set(const std::shared_ptr<PluginModel>& p); + + void add_preset(const URI& uri, const std::string& label); + +private: + static std::string get_documentation(const LilvNode* subject, bool html); + + static Sord::World* _rdf_world; + static LilvWorld* _lilv_world; + static const LilvPlugins* _lilv_plugins; + + Atom _type; + const LilvPlugin* _lilv_plugin; + Presets _presets; + bool _fetched{false}; +}; + +} // namespace client +} // namespace ingen + +#endif // INGEN_CLIENT_PLUGINMODEL_HPP diff --git a/include/ingen/client/PluginUI.hpp b/include/ingen/client/PluginUI.hpp new file mode 100644 index 00000000..b291d521 --- /dev/null +++ b/include/ingen/client/PluginUI.hpp @@ -0,0 +1,119 @@ +/* + This file is part of Ingen. + Copyright 2007-2015 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INGEN_CLIENT_PLUGINUI_HPP +#define INGEN_CLIENT_PLUGINUI_HPP + +#include "signal.hpp" + +#include "ingen/LV2Features.hpp" +#include "ingen/Resource.hpp" +#include "ingen/ingen.h" +#include "lilv/lilv.h" +#include "suil/suil.h" + +#include <cstdint> +#include <memory> +#include <set> + +namespace ingen { + +class Atom; +class URI; +class World; + +namespace client { + +class BlockModel; + +/** Custom user interface for a plugin. + * + * @ingroup IngenClient + */ +class INGEN_API PluginUI +{ +public: + ~PluginUI(); + + /** Create a UI for the given block and plugin. + * + * This does not actually instantiate the UI itself, so signals can be + * connected first. The caller should connect to signal_property_changed, + * then call instantiate(). + */ + static std::shared_ptr<PluginUI> + create(ingen::World& world, + const std::shared_ptr<const BlockModel>& block, + const LilvPlugin* plugin); + + /** Instantiate the UI. + * + * If true is returned, instantiation was successfull and the widget can be + * obtained with get_widget(). Otherwise, instantiation failed, so there is + * no widget and the UI can not be used. + */ + bool instantiate(); + bool instantiated () { return _instance != nullptr; } + + SuilWidget get_widget(); + + void port_event(uint32_t port_index, + uint32_t buffer_size, + uint32_t format, + const void* buffer); + + bool is_resizable() const; + + /** Signal emitted when the UI sets a property. + * + * The application must connect to this signal to communicate with the + * engine and/or update itself as necessary. + */ + INGEN_SIGNAL(property_changed, + void, + const URI&, // Subject + const URI&, // Predicate + const Atom&, // Object + Resource::Graph) // Context + + ingen::World& world() const { return _world; } + std::shared_ptr<const BlockModel> block() const { return _block; } + +private: + PluginUI(ingen::World& world, + std::shared_ptr<const BlockModel> block, + LilvUIs* uis, + const LilvUI* ui, + const LilvNode* ui_type); + + ingen::World& _world; + std::shared_ptr<const BlockModel> _block; + SuilInstance* _instance{nullptr}; + LilvUIs* _uis{nullptr}; + const LilvUI* _ui{nullptr}; + LilvNode* _ui_node{nullptr}; + LilvNode* _ui_type{nullptr}; + std::set<uint32_t> _subscribed_ports; + + static SuilHost* ui_host; + + std::shared_ptr<LV2Features::FeatureArray> _features; +}; + +} // namespace client +} // namespace ingen + +#endif // INGEN_CLIENT_PLUGINUI_HPP diff --git a/include/ingen/client/PortModel.hpp b/include/ingen/client/PortModel.hpp new file mode 100644 index 00000000..903a435d --- /dev/null +++ b/include/ingen/client/PortModel.hpp @@ -0,0 +1,101 @@ +/* + This file is part of Ingen. + Copyright 2007-2015 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INGEN_CLIENT_PORTMODEL_HPP +#define INGEN_CLIENT_PORTMODEL_HPP + +#include "ingen/Node.hpp" +#include "ingen/URI.hpp" +#include "ingen/URIs.hpp" +#include "ingen/client/ObjectModel.hpp" +#include "ingen/client/signal.hpp" +#include "ingen/ingen.h" +#include "raul/Path.hpp" + +#include <cstdint> +#include <memory> +#include <string> + +namespace ingen { + +class Atom; + +namespace client { + +/** Model of a port. + * + * @ingroup IngenClient + */ +class INGEN_API PortModel : public ObjectModel +{ +public: + enum class Direction { INPUT, OUTPUT }; + + GraphType graph_type() const override { return Node::GraphType::PORT; } + + bool supports(const URIs::Quark& value_type) const; + + uint32_t index() const { return _index; } + const Atom& value() const { return get_property(_uris.ingen_value); } + bool is_input() const { return (_direction == Direction::INPUT); } + bool is_output() const { return (_direction == Direction::OUTPUT); } + + bool port_property(const URIs::Quark& uri) const; + + bool is_logarithmic() const { return port_property(_uris.pprops_logarithmic); } + bool is_enumeration() const { return port_property(_uris.lv2_enumeration); } + bool is_integer() const { return port_property(_uris.lv2_integer); } + bool is_toggle() const { return port_property(_uris.lv2_toggled); } + bool is_numeric() const { + return ObjectModel::is_a(_uris.lv2_ControlPort) + || ObjectModel::is_a(_uris.lv2_CVPort); + } + bool is_uri() const; + + bool operator==(const PortModel& pm) const { return (path() == pm.path()); } + + void on_property(const URI& uri, const Atom& value) override; + + // Signals + INGEN_SIGNAL(value_changed, void, const Atom&) + INGEN_SIGNAL(voice_changed, void, uint32_t, const Atom&) + INGEN_SIGNAL(activity, void, const Atom&) + +private: + friend class ClientStore; + + PortModel(URIs& uris, + const raul::Path& path, + uint32_t index, + Direction dir) + : ObjectModel(uris, path) + , _index(index) + , _direction(dir) + {} + + void add_child(const std::shared_ptr<ObjectModel>& c) override { throw; } + bool remove_child(const std::shared_ptr<ObjectModel>& c) override { throw; } + + void set(const std::shared_ptr<ObjectModel>& model) override; + + uint32_t _index; + Direction _direction; +}; + +} // namespace client +} // namespace ingen + +#endif // INGEN_CLIENT_PORTMODEL_HPP diff --git a/include/ingen/client/SigClientInterface.hpp b/include/ingen/client/SigClientInterface.hpp new file mode 100644 index 00000000..6bff2e33 --- /dev/null +++ b/include/ingen/client/SigClientInterface.hpp @@ -0,0 +1,59 @@ +/* + This file is part of Ingen. + Copyright 2007-2016 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INGEN_CLIENT_SIGCLIENTINTERFACE_HPP +#define INGEN_CLIENT_SIGCLIENTINTERFACE_HPP + +#include "ingen/Interface.hpp" +#include "ingen/Message.hpp" +#include "ingen/URI.hpp" +#include "ingen/client/signal.hpp" +#include "ingen/ingen.h" + +namespace ingen::client { + +/** A LibSigC++ signal emitting interface for clients to use. + * + * This simply emits a signal for every event that comes from the engine. + * For a higher level model based view of the engine, use ClientStore. + * + * The signals here match the calls to ClientInterface exactly. See the + * documentation for ClientInterface for meanings of signal parameters. + * + * @ingroup IngenClient + */ +class INGEN_API SigClientInterface : public ingen::Interface, + public INGEN_TRACKABLE +{ +public: + SigClientInterface() = default; + + URI uri() const override { return URI("ingen:/clients/sig"); } + + INGEN_SIGNAL(message, void, Message) + + /** Fire pending signals. Only does anything on derived classes (that may queue) */ + virtual bool emit_signals() { return false; } + +protected: + void message(const Message& msg) override { + _signal_message(msg); + } +}; + +} // namespace ingen::client + +#endif diff --git a/include/ingen/client/SocketClient.hpp b/include/ingen/client/SocketClient.hpp new file mode 100644 index 00000000..7434da90 --- /dev/null +++ b/include/ingen/client/SocketClient.hpp @@ -0,0 +1,92 @@ +/* + This file is part of Ingen. + Copyright 2012-2015 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INGEN_CLIENT_SOCKETCLIENT_HPP +#define INGEN_CLIENT_SOCKETCLIENT_HPP + +#include "ingen/Log.hpp" +#include "ingen/SocketReader.hpp" +#include "ingen/SocketWriter.hpp" +#include "ingen/URI.hpp" +#include "ingen/World.hpp" +#include "ingen/ingen.h" +#include "raul/Socket.hpp" + +#include <cerrno> +#include <cstring> +#include <memory> + +namespace ingen { + +class Interface; + +namespace client { + +/** The client side of an Ingen socket connection. */ +class INGEN_API SocketClient : public SocketWriter +{ +public: + SocketClient(World& world, + const URI& uri, + const std::shared_ptr<raul::Socket>& sock, + const std::shared_ptr<Interface>& respondee) + : SocketWriter(world.uri_map(), world.uris(), uri, sock) + , _respondee(respondee) + , _reader(world, *respondee, sock) + {} + + std::shared_ptr<Interface> respondee() const override { + return _respondee; + } + + void set_respondee(const std::shared_ptr<Interface>& respondee) override + { + _respondee = respondee; + } + + static std::shared_ptr<ingen::Interface> + new_socket_interface(ingen::World& world, + const URI& uri, + const std::shared_ptr<ingen::Interface>& respondee) + { + const raul::Socket::Type type = (uri.scheme() == "unix" + ? raul::Socket::Type::UNIX + : raul::Socket::Type::TCP); + + const std::shared_ptr<raul::Socket> sock{new raul::Socket(type)}; + if (!sock->connect(uri)) { + world.log().error("Failed to connect <%1%> (%2%)\n", + sock->uri(), strerror(errno)); + return nullptr; + } + return std::shared_ptr<Interface>( + new SocketClient(world, uri, sock, respondee)); + } + + static void register_factories(World& world) { + world.add_interface_factory("unix", &new_socket_interface); + world.add_interface_factory("tcp", &new_socket_interface); + } + +private: + std::shared_ptr<Interface> _respondee; + SocketReader _reader; +}; + +} // namespace client +} // namespace ingen + +#endif // INGEN_CLIENT_SOCKETCLIENT_HPP diff --git a/include/ingen/client/client.h b/include/ingen/client/client.h new file mode 100644 index 00000000..6f7ac9b5 --- /dev/null +++ b/include/ingen/client/client.h @@ -0,0 +1,31 @@ +/* + This file is part of Ingen. + Copyright 2014-2022 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INGEN_CLIENT_CLIENT_H +#define INGEN_CLIENT_CLIENT_H + +#if defined(_WIN32) && !defined(INGEN_CLIENT_STATIC) && \ + defined(INGEN_CLIENT_INTERNAL) +# define INGEN_CLIENT_API __declspec(dllexport) +#elif defined(_WIN32) && !defined(INGEN_CLIENT_STATIC) +# define INGEN_CLIENT_API __declspec(dllimport) +#elif defined(__GNUC__) +# define INGEN_CLIENT_API __attribute__((visibility("default"))) +#else +# define INGEN_CLIENT_API +#endif + +#endif // INGEN_CLIENT_CLIENT_H diff --git a/include/ingen/client/signal.hpp b/include/ingen/client/signal.hpp new file mode 100644 index 00000000..ea382549 --- /dev/null +++ b/include/ingen/client/signal.hpp @@ -0,0 +1,34 @@ +/* + This file is part of Ingen. + Copyright 2007-2015 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INGEN_CLIENT_SIGNAL_HPP +#define INGEN_CLIENT_SIGNAL_HPP + +// IWYU pragma: begin_exports +#include <sigc++/signal.h> +#include <sigc++/trackable.h> +// IWYU pragma: end_exports + +#define INGEN_SIGNAL(name, ...) \ +protected: \ +sigc::signal<__VA_ARGS__> _signal_##name; \ +public: \ +sigc::signal<__VA_ARGS__> signal_##name() const { return _signal_##name; } \ +sigc::signal<__VA_ARGS__>& signal_##name() { return _signal_##name; } + +#define INGEN_TRACKABLE sigc::trackable + +#endif // INGEN_CLIENT_SIGNAL_HPP |