diff options
Diffstat (limited to 'ingen/client')
-rw-r--r-- | ingen/client/ArcModel.hpp | 68 | ||||
-rw-r--r-- | ingen/client/BlockModel.hpp | 118 | ||||
-rw-r--r-- | ingen/client/ClientStore.hpp | 127 | ||||
-rw-r--r-- | ingen/client/GraphModel.hpp | 74 | ||||
-rw-r--r-- | ingen/client/ObjectModel.hpp | 103 | ||||
-rw-r--r-- | ingen/client/PluginModel.hpp | 128 | ||||
-rw-r--r-- | ingen/client/PluginUI.hpp | 111 | ||||
-rw-r--r-- | ingen/client/PortModel.hpp | 97 | ||||
-rw-r--r-- | ingen/client/SigClientInterface.hpp | 64 | ||||
-rw-r--r-- | ingen/client/SocketClient.hpp | 80 | ||||
-rw-r--r-- | ingen/client/signal.hpp | 31 |
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 |