summaryrefslogtreecommitdiffstats
path: root/ingen/client
diff options
context:
space:
mode:
Diffstat (limited to 'ingen/client')
-rw-r--r--ingen/client/ArcModel.hpp68
-rw-r--r--ingen/client/BlockModel.hpp118
-rw-r--r--ingen/client/ClientStore.hpp127
-rw-r--r--ingen/client/GraphModel.hpp74
-rw-r--r--ingen/client/ObjectModel.hpp103
-rw-r--r--ingen/client/PluginModel.hpp128
-rw-r--r--ingen/client/PluginUI.hpp111
-rw-r--r--ingen/client/PortModel.hpp97
-rw-r--r--ingen/client/SigClientInterface.hpp64
-rw-r--r--ingen/client/SocketClient.hpp80
-rw-r--r--ingen/client/signal.hpp31
11 files changed, 1001 insertions, 0 deletions
diff --git a/ingen/client/ArcModel.hpp b/ingen/client/ArcModel.hpp
new file mode 100644
index 00000000..8b129a00
--- /dev/null
+++ b/ingen/client/ArcModel.hpp
@@ -0,0 +1,68 @@
+/*
+ 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 <cassert>
+
+#include "ingen/types.hpp"
+#include "raul/Path.hpp"
+
+#include "ingen/Arc.hpp"
+#include "ingen/client/PortModel.hpp"
+#include "ingen/ingen.h"
+
+namespace Ingen {
+namespace Client {
+
+class ClientStore;
+
+/** Class to represent a port->port connections in the engine.
+ *
+ * @ingroup IngenClient
+ */
+class INGEN_API ArcModel : public Arc
+{
+public:
+ SPtr<PortModel> tail() const { return _tail; }
+ SPtr<PortModel> head() const { return _head; }
+
+ const Raul::Path& tail_path() const { return _tail->path(); }
+ const Raul::Path& head_path() const { return _head->path(); }
+
+private:
+ friend class ClientStore;
+
+ ArcModel(SPtr<PortModel> tail, SPtr<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 SPtr<PortModel> _tail;
+ const SPtr<PortModel> _head;
+};
+
+} // namespace Client
+} // namespace Ingen
+
+#endif // INGEN_CLIENT_ARCMODEL_HPP
diff --git a/ingen/client/BlockModel.hpp b/ingen/client/BlockModel.hpp
new file mode 100644
index 00000000..38e8987e
--- /dev/null
+++ b/ingen/client/BlockModel.hpp
@@ -0,0 +1,118 @@
+/*
+ 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 <cstdlib>
+#include <string>
+#include <vector>
+
+#include "ingen/Node.hpp"
+#include "ingen/client/ObjectModel.hpp"
+#include "ingen/client/PluginModel.hpp"
+#include "ingen/client/PortModel.hpp"
+#include "ingen/ingen.h"
+#include "ingen/types.hpp"
+
+namespace Raul { class Path; }
+
+namespace Ingen {
+
+class URIs;
+
+namespace Client {
+
+class PluginModel;
+class ClientStore;
+
+/** 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);
+ virtual ~BlockModel();
+
+ GraphType graph_type() const { return Node::GraphType::BLOCK; }
+
+ typedef std::vector< SPtr<const PortModel> > Ports;
+
+ SPtr<const PortModel> get_port(const Raul::Symbol& symbol) const;
+ SPtr<const PortModel> get_port(uint32_t index) const;
+
+ Node* port(uint32_t index) const;
+
+ const URI& plugin_uri() const { return _plugin_uri; }
+ const Resource* plugin() const { return _plugin.get(); }
+ Resource* plugin() { return _plugin.get(); }
+ SPtr<PluginModel> plugin_model() const { return _plugin; }
+ uint32_t num_ports() const { return _ports.size(); }
+ const Ports& ports() const { return _ports; }
+
+ void default_port_value_range(SPtr<const PortModel> port,
+ float& min,
+ float& max,
+ uint32_t srate = 1) const;
+
+ void port_value_range(SPtr<const PortModel> port,
+ float& min,
+ float& max,
+ uint32_t srate = 1) const;
+
+ std::string label() const;
+ std::string port_label(SPtr<const PortModel> port) const;
+
+ // Signals
+ INGEN_SIGNAL(new_port, void, SPtr<const PortModel>);
+ INGEN_SIGNAL(removed_port, void, SPtr<const PortModel>);
+
+protected:
+ friend class ClientStore;
+
+ BlockModel(URIs& uris,
+ const URI& plugin_uri,
+ const Raul::Path& path);
+ BlockModel(URIs& uris,
+ SPtr<PluginModel> plugin,
+ const Raul::Path& path);
+ explicit BlockModel(const Raul::Path& path);
+
+ void add_child(SPtr<ObjectModel> c);
+ bool remove_child(SPtr<ObjectModel> c);
+ void add_port(SPtr<PortModel> pm);
+ void remove_port(SPtr<PortModel> port);
+ void remove_port(const Raul::Path& port_path);
+ void set(SPtr<ObjectModel> model);
+
+ virtual void clear();
+
+ Ports _ports; ///< Vector of ports
+ URI _plugin_uri; ///< Plugin URI (if PluginModel is unknown)
+ SPtr<PluginModel> _plugin; ///< The plugin this block 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/ingen/client/ClientStore.hpp b/ingen/client/ClientStore.hpp
new file mode 100644
index 00000000..797052ef
--- /dev/null
+++ b/ingen/client/ClientStore.hpp
@@ -0,0 +1,127 @@
+/*
+ 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 <cassert>
+#include <list>
+#include <string>
+
+#include "ingen/Interface.hpp"
+#include "ingen/Store.hpp"
+#include "ingen/client/signal.hpp"
+#include "ingen/ingen.h"
+#include "ingen/types.hpp"
+#include "raul/Path.hpp"
+
+namespace Raul { class Atom; }
+
+namespace Ingen {
+
+class Log;
+class Node;
+class URIs;
+
+namespace Client {
+
+class BlockModel;
+class GraphModel;
+class ObjectModel;
+class PluginModel;
+class PortModel;
+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,
+ SPtr<SigClientInterface> emitter = SPtr<SigClientInterface>());
+
+ URI uri() const override { return URI("ingen:/clients/store"); }
+
+ SPtr<const ObjectModel> object(const Raul::Path& path) const;
+ SPtr<const PluginModel> plugin(const URI& uri) const;
+ SPtr<const Resource> resource(const URI& uri) const;
+
+ void clear();
+
+ typedef std::map< const URI, SPtr<PluginModel> > Plugins;
+ SPtr<const Plugins> plugins() const { return _plugins; }
+ SPtr<Plugins> plugins() { return _plugins; }
+ void set_plugins(SPtr<Plugins> p) { _plugins = p; }
+
+ URIs& uris() { return _uris; }
+
+ void message(const Message& msg) override;
+
+ void operator()(const BundleBegin&) {}
+ void operator()(const BundleEnd&) {}
+ 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&) {}
+ void operator()(const Get&) {}
+ void operator()(const Move&);
+ void operator()(const Put&);
+ void operator()(const Redo&) {}
+ void operator()(const Response&) {}
+ void operator()(const SetProperty&);
+ void operator()(const Undo&) {}
+
+ INGEN_SIGNAL(new_object, void, SPtr<ObjectModel>);
+ INGEN_SIGNAL(new_plugin, void, SPtr<PluginModel>);
+ INGEN_SIGNAL(plugin_deleted, void, URI);
+
+private:
+ SPtr<ObjectModel> _object(const Raul::Path& path);
+ SPtr<PluginModel> _plugin(const URI& uri);
+ SPtr<PluginModel> _plugin(const Atom& uri);
+ SPtr<Resource> _resource(const URI& uri);
+
+ void add_object(SPtr<ObjectModel> object);
+ SPtr<ObjectModel> remove_object(const Raul::Path& path);
+
+ void add_plugin(SPtr<PluginModel> pm);
+
+ SPtr<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;
+ SPtr<SigClientInterface> _emitter;
+
+ SPtr<Plugins> _plugins; ///< Map, keyed by plugin URI
+};
+
+} // namespace Client
+} // namespace Ingen
+
+#endif // INGEN_CLIENT_CLIENTSTORE_HPP
diff --git a/ingen/client/GraphModel.hpp b/ingen/client/GraphModel.hpp
new file mode 100644
index 00000000..ef072d87
--- /dev/null
+++ b/ingen/client/GraphModel.hpp
@@ -0,0 +1,74 @@
+/*
+ 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/client/BlockModel.hpp"
+#include "ingen/ingen.h"
+#include "ingen/types.hpp"
+
+namespace Ingen {
+namespace Client {
+
+class ArcModel;
+class ClientStore;
+
+/** 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 { return Node::GraphType::GRAPH; }
+
+ SPtr<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, SPtr<BlockModel>);
+ INGEN_SIGNAL(removed_block, void, SPtr<BlockModel>);
+ INGEN_SIGNAL(new_arc, void, SPtr<ArcModel>);
+ INGEN_SIGNAL(removed_arc, void, SPtr<ArcModel>);
+
+private:
+ friend class ClientStore;
+
+ GraphModel(URIs& uris, const Raul::Path& graph_path)
+ : BlockModel(uris, uris.ingen_Graph, graph_path)
+ {}
+
+ void clear();
+ void add_child(SPtr<ObjectModel> c);
+ bool remove_child(SPtr<ObjectModel> o);
+ void remove_arcs_on(SPtr<PortModel> p);
+
+ void add_arc(SPtr<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/ingen/client/ObjectModel.hpp b/ingen/client/ObjectModel.hpp
new file mode 100644
index 00000000..a5a68f1e
--- /dev/null
+++ b/ingen/client/ObjectModel.hpp
@@ -0,0 +1,103 @@
+/*
+ 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 <algorithm>
+#include <cassert>
+#include <cstdlib>
+
+#include "ingen/types.hpp"
+#include "raul/Path.hpp"
+
+#include "ingen/Node.hpp"
+#include "ingen/Resource.hpp"
+#include "ingen/client/signal.hpp"
+#include "ingen/ingen.h"
+
+namespace Ingen {
+
+class URIs;
+
+namespace Client {
+
+class ClientStore;
+
+/** 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;
+
+ void on_property(const URI& uri, const Atom& value);
+ void on_property_removed(const URI& uri, const Atom& value);
+
+ const Raul::Path& path() const { return _path; }
+ const Raul::Symbol& symbol() const { return _symbol; }
+ SPtr<ObjectModel> parent() const { return _parent; }
+ bool polyphonic() const;
+
+ Node* graph_parent() const { return _parent.get(); }
+
+ // Signals
+ INGEN_SIGNAL(new_child, void, SPtr<ObjectModel>);
+ INGEN_SIGNAL(removed_child, void, SPtr<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);
+
+ virtual void set_path(const Raul::Path& p);
+ virtual void set_parent(SPtr<ObjectModel> p);
+ virtual void add_child(SPtr<ObjectModel> c) {}
+ virtual bool remove_child(SPtr<ObjectModel> c) { return true; }
+
+ virtual void set(SPtr<ObjectModel> o);
+
+ SPtr<ObjectModel> _parent;
+
+private:
+ Raul::Path _path;
+ Raul::Symbol _symbol;
+};
+
+} // namespace Client
+} // namespace Ingen
+
+#endif // INGEN_CLIENT_OBJECTMODEL_HPP
diff --git a/ingen/client/PluginModel.hpp b/ingen/client/PluginModel.hpp
new file mode 100644
index 00000000..61de0f1a
--- /dev/null
+++ b/ingen/client/PluginModel.hpp
@@ -0,0 +1,128 @@
+/*
+ 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 <list>
+#include <map>
+#include <string>
+#include <utility>
+
+#include "ingen/Forge.hpp"
+#include "ingen/Resource.hpp"
+#include "ingen/World.hpp"
+#include "ingen/client/signal.hpp"
+#include "ingen/ingen.h"
+#include "ingen/types.hpp"
+#include "lilv/lilv.h"
+#include "raul/Symbol.hpp"
+#include "sord/sordmm.hpp"
+
+namespace Ingen {
+
+class URIs;
+
+namespace Client {
+
+class GraphModel;
+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; }
+
+ const URI type_uri() const
+ {
+ return URI(_type.is_valid() ? _uris.forge.str(_type, false)
+ : "http://www.w3.org/2002/07/owl#Nothing");
+ }
+
+ virtual const Atom& get_property(const URI& key) const;
+
+ Raul::Symbol default_block_symbol() const;
+ std::string human_name() const;
+ std::string port_human_name(uint32_t i) const;
+
+ typedef std::map<float, std::string> ScalePoints;
+ ScalePoints port_scale_points(uint32_t i) const;
+
+ typedef std::map<URI, std::string> Presets;
+ 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;
+
+ SPtr<PluginUI> ui(Ingen::World* world,
+ SPtr<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(SPtr<PluginModel> p);
+
+ void add_preset(const URI& uri, const std::string& label);
+
+private:
+ std::string get_documentation(const LilvNode* subject, bool html) const;
+
+ static Sord::World* _rdf_world;
+ static LilvWorld* _lilv_world;
+ static const LilvPlugins* _lilv_plugins;
+
+ Atom _type;
+ const LilvPlugin* _lilv_plugin;
+ Presets _presets;
+ bool _fetched;
+};
+
+} // namespace Client
+} // namespace Ingen
+
+#endif // INGEN_CLIENT_PLUGINMODEL_HPP
diff --git a/ingen/client/PluginUI.hpp b/ingen/client/PluginUI.hpp
new file mode 100644
index 00000000..a98df61d
--- /dev/null
+++ b/ingen/client/PluginUI.hpp
@@ -0,0 +1,111 @@
+/*
+ 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 <set>
+
+#include "ingen/LV2Features.hpp"
+#include "ingen/ingen.h"
+#include "ingen/types.hpp"
+#include "lilv/lilv.h"
+#include "suil/suil.h"
+
+namespace Ingen {
+
+class Interface;
+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 SPtr<PluginUI> create(Ingen::World* world,
+ SPtr<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; }
+ SPtr<const BlockModel> block() const { return _block; }
+
+private:
+ PluginUI(Ingen::World* world,
+ SPtr<const BlockModel> block,
+ LilvUIs* uis,
+ const LilvUI* ui,
+ const LilvNode* ui_type);
+
+ Ingen::World* _world;
+ SPtr<const BlockModel> _block;
+ SuilInstance* _instance;
+ LilvUIs* _uis;
+ const LilvUI* _ui;
+ LilvNode* _ui_node;
+ LilvNode* _ui_type;
+ std::set<uint32_t> _subscribed_ports;
+
+ static SuilHost* ui_host;
+
+ SPtr<LV2Features::FeatureArray> _features;
+};
+
+} // namespace Client
+} // namespace Ingen
+
+#endif // INGEN_CLIENT_PLUGINUI_HPP
diff --git a/ingen/client/PortModel.hpp b/ingen/client/PortModel.hpp
new file mode 100644
index 00000000..9ad37378
--- /dev/null
+++ b/ingen/client/PortModel.hpp
@@ -0,0 +1,97 @@
+/*
+ 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 <cstdlib>
+#include <string>
+
+#include "ingen/client/ObjectModel.hpp"
+#include "ingen/ingen.h"
+#include "ingen/types.hpp"
+#include "lv2/lv2plug.in/ns/ext/port-props/port-props.h"
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+
+namespace Raul { class Path; }
+
+namespace Ingen {
+namespace Client {
+
+/** Model of a port.
+ *
+ * @ingroup IngenClient
+ */
+class INGEN_API PortModel : public ObjectModel
+{
+public:
+ enum class Direction { INPUT, OUTPUT };
+
+ GraphType graph_type() const { return Node::GraphType::PORT; }
+
+ bool supports(const URIs::Quark& value_type) const;
+
+ inline uint32_t index() const { return _index; }
+ inline const Atom& value() const { return get_property(_uris.ingen_value); }
+ inline bool is_input() const { return (_direction == Direction::INPUT); }
+ inline 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;
+
+ inline bool operator==(const PortModel& pm) const { return (path() == pm.path()); }
+
+ void on_property(const URI& uri, const Atom& value);
+
+ // 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(SPtr<ObjectModel> c) { throw; }
+ bool remove_child(SPtr<ObjectModel> c) { throw; }
+
+ void set(SPtr<ObjectModel> model);
+
+ uint32_t _index;
+ Direction _direction;
+};
+
+} // namespace Client
+} // namespace Ingen
+
+#endif // INGEN_CLIENT_PORTMODEL_HPP
diff --git a/ingen/client/SigClientInterface.hpp b/ingen/client/SigClientInterface.hpp
new file mode 100644
index 00000000..8ac8dca4
--- /dev/null
+++ b/ingen/client/SigClientInterface.hpp
@@ -0,0 +1,64 @@
+/*
+ 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 <cstdint>
+#include <string>
+
+#include "raul/Path.hpp"
+
+#include "ingen/Interface.hpp"
+#include "ingen/client/signal.hpp"
+#include "ingen/ingen.h"
+
+namespace Ingen {
+namespace 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() {}
+
+ 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 Client
+} // namespace Ingen
+
+#endif
diff --git a/ingen/client/SocketClient.hpp b/ingen/client/SocketClient.hpp
new file mode 100644
index 00000000..8236200b
--- /dev/null
+++ b/ingen/client/SocketClient.hpp
@@ -0,0 +1,80 @@
+/*
+ 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_SOCKET_CLIENT_HPP
+#define INGEN_CLIENT_SOCKET_CLIENT_HPP
+
+#include "ingen/SocketReader.hpp"
+#include "ingen/SocketWriter.hpp"
+#include "ingen/ingen.h"
+#include "raul/Socket.hpp"
+
+namespace Ingen {
+namespace Client {
+
+/** The client side of an Ingen socket connection. */
+class INGEN_API SocketClient : public SocketWriter
+{
+public:
+ SocketClient(World& world,
+ const URI& uri,
+ SPtr<Raul::Socket> sock,
+ SPtr<Interface> respondee)
+ : SocketWriter(world.uri_map(), world.uris(), uri, sock)
+ , _respondee(respondee)
+ , _reader(world, *respondee.get(), sock)
+ {}
+
+ SPtr<Interface> respondee() const override {
+ return _respondee;
+ }
+
+ void set_respondee(SPtr<Interface> respondee) override {
+ _respondee = respondee;
+ }
+
+ static SPtr<Ingen::Interface>
+ new_socket_interface(Ingen::World* world,
+ const URI& uri,
+ SPtr<Ingen::Interface> respondee)
+ {
+ const Raul::Socket::Type type = (uri.scheme() == "unix"
+ ? Raul::Socket::Type::UNIX
+ : Raul::Socket::Type::TCP);
+
+ SPtr<Raul::Socket> sock(new Raul::Socket(type));
+ if (!sock->connect(uri)) {
+ world->log().error(fmt("Failed to connect <%1%> (%2%)\n")
+ % sock->uri() % strerror(errno));
+ return SPtr<Interface>();
+ }
+ return SPtr<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:
+ SPtr<Interface> _respondee;
+ SocketReader _reader;
+};
+
+} // namespace Client
+} // namespace Ingen
+
+#endif // INGEN_CLIENT_SOCKET_CLIENT_HPP
diff --git a/ingen/client/signal.hpp b/ingen/client/signal.hpp
new file mode 100644
index 00000000..ba5b017b
--- /dev/null
+++ b/ingen/client/signal.hpp
@@ -0,0 +1,31 @@
+/*
+ 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
+
+#include <sigc++/sigc++.h>
+
+#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