summaryrefslogtreecommitdiffstats
path: root/src/shared
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/Builder.cpp98
-rw-r--r--src/shared/Builder.hpp57
-rw-r--r--src/shared/ClashAvoider.cpp214
-rw-r--r--src/shared/ClashAvoider.hpp108
-rw-r--r--src/shared/LV2Features.cpp66
-rw-r--r--src/shared/LV2Features.hpp63
-rw-r--r--src/shared/LV2URIMap.cpp75
-rw-r--r--src/shared/LV2URIMap.hpp64
-rw-r--r--src/shared/Makefile.am22
-rw-r--r--src/shared/OSCSender.cpp125
-rw-r--r--src/shared/OSCSender.hpp59
-rw-r--r--src/shared/Store.cpp108
-rw-r--r--src/shared/Store.hpp60
-rw-r--r--src/shared/wscript19
14 files changed, 1138 insertions, 0 deletions
diff --git a/src/shared/Builder.cpp b/src/shared/Builder.cpp
new file mode 100644
index 00000000..1eb127a5
--- /dev/null
+++ b/src/shared/Builder.cpp
@@ -0,0 +1,98 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "Builder.hpp"
+#include "common/interface/CommonInterface.hpp"
+#include "common/interface/Patch.hpp"
+#include "common/interface/Node.hpp"
+#include "common/interface/Port.hpp"
+#include "common/interface/Connection.hpp"
+#include "common/interface/Plugin.hpp"
+#include <iostream>
+using namespace std;
+
+namespace Ingen {
+namespace Shared {
+
+
+Builder::Builder(CommonInterface& interface)
+ : _interface(interface)
+{
+}
+
+
+void
+Builder::build(const Raul::Path& prefix, SharedPtr<const GraphObject> object)
+{
+ SharedPtr<const Patch> patch = PtrCast<const Patch>(object);
+ if (patch) {
+ if (object->path() != "/") {
+ const std::string path_str = prefix.base() + object->path().substr(1);
+ //cout << "BUILDING PATCH " << path_str << endl;
+ _interface.new_patch(path_str, patch->internal_polyphony());
+ }
+
+ build_object(prefix, object);
+ for (Patch::Connections::const_iterator i = patch->connections().begin();
+ i != patch->connections().end(); ++i) {
+ string base = prefix.base() + object->path().substr(1);
+ cout << "*********** BASE: " << base << endl;
+ _interface.connect(base + (*i)->src_port_path().substr(1),
+ base + (*i)->dst_port_path().substr(1));
+ }
+ return;
+ }
+
+ SharedPtr<const Node> node = PtrCast<const Node>(object);
+ if (node) {
+ Raul::Path path = prefix.base() + node->path().substr(1);
+ //cout << "BUILDING NODE " << path << endl;
+ _interface.new_node(path, node->plugin()->uri());
+ build_object(prefix, object);
+ return;
+ }
+
+ SharedPtr<const Port> port = PtrCast<const Port>(object);
+ if (port) {
+ Raul::Path path = prefix.base() + port->path().substr(1);
+ //cout << "BUILDING PORT " << path << endl;
+ _interface.new_port(path, port->index(), port->type().uri(), !port->is_input());
+ build_object(prefix, object);
+ return;
+ }
+}
+
+
+void
+Builder::build_object(const Raul::Path& prefix, SharedPtr<const GraphObject> object)
+{
+ for (GraphObject::Variables::const_iterator i = object->variables().begin();
+ i != object->variables().end(); ++i)
+ _interface.set_variable(prefix.base() + object->path().substr(1), i->first, i->second);
+
+ for (GraphObject::Properties::const_iterator i = object->properties().begin();
+ i != object->properties().end(); ++i) {
+ if (object->path() == "/")
+ continue;
+ string path_str = prefix.base() + object->path().substr(1);
+ _interface.set_property(prefix.base() + object->path().substr(1), i->first, i->second);
+ }
+}
+
+
+} // namespace Shared
+} // namespace Ingen
diff --git a/src/shared/Builder.hpp b/src/shared/Builder.hpp
new file mode 100644
index 00000000..a980bad2
--- /dev/null
+++ b/src/shared/Builder.hpp
@@ -0,0 +1,57 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef BUILDER_H
+#define BUILDER_H
+
+#include <raul/SharedPtr.hpp>
+
+namespace Raul { class Path; }
+
+namespace Ingen {
+namespace Shared {
+
+class GraphObject;
+class CommonInterface;
+
+
+/** Wrapper for CommonInterface to create existing objects/models.
+ *
+ * \ingroup interface
+ */
+class Builder
+{
+public:
+ Builder(CommonInterface& interface);
+ virtual ~Builder() {}
+
+ void build(const Raul::Path& prefix,
+ SharedPtr<const GraphObject> object);
+
+private:
+ void build_object(const Raul::Path& prefix,
+ SharedPtr<const GraphObject> object);
+
+ CommonInterface& _interface;
+};
+
+
+} // namespace Shared
+} // namespace Ingen
+
+#endif // BUILDER_H
+
diff --git a/src/shared/ClashAvoider.cpp b/src/shared/ClashAvoider.cpp
new file mode 100644
index 00000000..d5d1d245
--- /dev/null
+++ b/src/shared/ClashAvoider.cpp
@@ -0,0 +1,214 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "ClashAvoider.hpp"
+#include "Store.hpp"
+
+using namespace std;
+using namespace Raul;
+
+namespace Ingen {
+namespace Shared {
+
+
+const Raul::Path
+ClashAvoider::map_path(const Raul::Path& in)
+{
+ //cout << "MAP PATH: " << in << endl;
+
+ unsigned offset = 0;
+ bool has_offset = false;
+ size_t pos = in.find_last_of("_");
+ if (pos != string::npos && pos != (in.length()-1)) {
+ const std::string trailing = in.substr(in.find_last_of("_")+1);
+ has_offset = (sscanf(trailing.c_str(), "%u", &offset) > 0);
+ }
+
+ //cout << "HAS OFFSET: " << offset << endl;
+
+ // Path without _n suffix
+ Path base_path = in;
+ if (has_offset)
+ base_path = base_path.substr(0, base_path.find_last_of("_"));
+
+ //cout << "\tBASE: " << base_path << endl;
+
+ SymbolMap::iterator m = _symbol_map.find(in);
+ if (m != _symbol_map.end()) {
+ //cout << " (1) " << m->second << endl;
+ return m->second;
+ } else {
+ typedef std::pair<SymbolMap::iterator, bool> InsertRecord;
+
+ // No clash, use symbol unmodified
+ if (!exists(in) && _symbol_map.find(in) == _symbol_map.end()) {
+ InsertRecord i = _symbol_map.insert(make_pair(in, in));
+ assert(i.second);
+ //cout << " (2) " << i.first->second << endl;;
+ return i.first->second;
+ } else {
+
+ // See if the parent is mapped
+ // FIXME: do this the other way around
+ Path parent = in.parent();
+ do {
+ SymbolMap::iterator p = _symbol_map.find(parent);
+ if (p != _symbol_map.end()) {
+ const Path mapped = p->second.base() + in.substr(parent.base().length());
+ InsertRecord i = _symbol_map.insert(make_pair(in, mapped));
+ //cout << " (3) " << _prefix.base() + i.first->second.substr(1) << endl;
+ return i.first->second;
+ }
+ parent = parent.parent();
+ } while (parent != "/");
+
+ // Append _2 _3 etc until an unused symbol is found
+ while (true) {
+ Offsets::iterator o = _offsets.find(base_path);
+ if (o != _offsets.end()) {
+ offset = ++o->second;
+ } else {
+ string parent_str = _prefix.base() + in.parent().base().substr(1);
+ parent_str = parent_str.substr(0, parent_str.find_last_of("/"));
+ if (parent_str == "")
+ parent_str = "/";
+ //cout << "***** PARENT: " << parent_str << endl;
+ }
+
+ std::stringstream ss;
+ ss << base_path << "_" << offset;
+ if (!exists(ss.str())) {
+ string str = ss.str();
+ InsertRecord i = _symbol_map.insert(make_pair(in, str));
+ //cout << "HIT: offset = " << offset << ", str = " << str << endl;
+ offset = _store.child_name_offset(in.parent(), base_path.name(), false);
+ _offsets.insert(make_pair(base_path, offset));
+ //cout << " (4) " << i.first->second << endl;;
+ return i.first->second;
+ } else {
+ //cout << "MISSED OFFSET: " << in << " => " << ss.str() << endl;
+ if (o != _offsets.end())
+ offset = ++o->second;
+ else
+ ++offset;
+ }
+ }
+ }
+ }
+}
+
+
+bool
+ClashAvoider::exists(const Raul::Path& path) const
+{
+ bool exists = (_store.find(_prefix.base() + path.substr(1)) != _store.end());
+ if (exists)
+ return true;
+
+ if (_also_avoid)
+ return (_also_avoid->find(path) != _also_avoid->end());
+ else
+ return false;
+}
+
+
+void
+ClashAvoider::new_patch(const std::string& path,
+ uint32_t poly)
+{
+ _target.new_patch(map_path(path), poly);
+}
+
+
+void
+ClashAvoider::new_node(const std::string& path,
+ const std::string& plugin_uri)
+{
+ _target.new_node(map_path(path), plugin_uri);
+}
+
+
+void
+ClashAvoider::new_port(const std::string& path,
+ uint32_t index,
+ const std::string& data_type,
+ bool is_output)
+{
+ _target.new_port(map_path(path), index, data_type, is_output);
+}
+
+
+void
+ClashAvoider::connect(const std::string& src_port_path,
+ const std::string& dst_port_path)
+{
+ _target.connect(map_path(src_port_path), map_path(dst_port_path));
+}
+
+
+void
+ClashAvoider::disconnect(const std::string& src_port_path,
+ const std::string& dst_port_path)
+{
+ _target.disconnect(map_path(src_port_path), map_path(dst_port_path));
+}
+
+
+void
+ClashAvoider::set_variable(const std::string& subject_path,
+ const std::string& predicate,
+ const Raul::Atom& value)
+{
+ _target.set_variable(map_path(subject_path), predicate, value);
+}
+
+
+void
+ClashAvoider::set_property(const std::string& subject_path,
+ const std::string& predicate,
+ const Raul::Atom& value)
+{
+ _target.set_property(map_path(subject_path), predicate, value);
+}
+
+
+void
+ClashAvoider::set_port_value(const std::string& port_path,
+ const Raul::Atom& value)
+{
+ _target.set_port_value(map_path(port_path), value);
+}
+
+
+void
+ClashAvoider::set_voice_value(const std::string& port_path,
+ uint32_t voice,
+ const Raul::Atom& value)
+{
+ _target.set_voice_value(map_path(port_path), voice, value);
+}
+
+
+void
+ClashAvoider::destroy(const std::string& path)
+{
+ _target.destroy(map_path(path));
+}
+
+
+} // namespace Shared
+} // namespace Ingen
diff --git a/src/shared/ClashAvoider.hpp b/src/shared/ClashAvoider.hpp
new file mode 100644
index 00000000..f7016e4e
--- /dev/null
+++ b/src/shared/ClashAvoider.hpp
@@ -0,0 +1,108 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef CLASHAVOIDER_H
+#define CLASHAVOIDER_H
+
+#include <inttypes.h>
+#include <string>
+#include <map>
+#include <raul/Atom.hpp>
+#include <raul/Path.hpp>
+#include "interface/CommonInterface.hpp"
+
+namespace Ingen {
+namespace Shared {
+
+class Store;
+
+
+/** A wrapper for a CommonInterface that creates objects but possibly maps
+ * symbol names to avoid clashes with the existing objects in a store.
+ */
+class ClashAvoider : public CommonInterface
+{
+public:
+ ClashAvoider(Store& store, const Raul::Path& prefix, CommonInterface& target,
+ Store* also_avoid=NULL)
+ : _prefix(prefix), _store(store), _target(target), _also_avoid(also_avoid) {}
+
+ void set_target(CommonInterface& target) { _target = target; }
+
+ // Bundles
+ void bundle_begin() { _target.bundle_begin(); }
+ void bundle_end() { _target.bundle_end(); }
+
+ // Object commands
+
+ void new_patch(const std::string& path,
+ uint32_t poly);
+
+ void new_node(const std::string& path,
+ const std::string& plugin_uri);
+
+ void new_port(const std::string& path,
+ uint32_t index,
+ const std::string& data_type,
+ bool is_output);
+
+ void connect(const std::string& src_port_path,
+ const std::string& dst_port_path);
+
+ void disconnect(const std::string& src_port_path,
+ const std::string& dst_port_path);
+
+ void set_variable(const std::string& subject_path,
+ const std::string& predicate,
+ const Raul::Atom& value);
+
+ void set_property(const std::string& subject_path,
+ const std::string& predicate,
+ const Raul::Atom& value);
+
+ void set_port_value(const std::string& port_path,
+ const Raul::Atom& value);
+
+ void set_voice_value(const std::string& port_path,
+ uint32_t voice,
+ const Raul::Atom& value);
+
+ void destroy(const std::string& path);
+
+private:
+ const Raul::Path map_path(const Raul::Path& in);
+
+ const Raul::Path& _prefix;
+ Store& _store;
+ CommonInterface& _target;
+
+ Store* _also_avoid;
+ bool exists(const Raul::Path& path) const;
+
+ typedef std::map<Raul::Path, unsigned> Offsets;
+ Offsets _offsets;
+
+ typedef std::map<Raul::Path, Raul::Path> SymbolMap;
+ SymbolMap _symbol_map;
+};
+
+
+} // namespace Shared
+} // namespace Ingen
+
+#endif // CLASHAVOIDER_H
+
diff --git a/src/shared/LV2Features.cpp b/src/shared/LV2Features.cpp
new file mode 100644
index 00000000..2e7eb10e
--- /dev/null
+++ b/src/shared/LV2Features.cpp
@@ -0,0 +1,66 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <cstdlib>
+#include "LV2Features.hpp"
+#include "LV2URIMap.hpp"
+
+using namespace std;
+
+namespace Ingen {
+namespace Shared {
+
+
+LV2Features::LV2Features()
+ : _lv2_features((LV2_Feature**)malloc(sizeof(LV2_Feature*)))
+{
+ _lv2_features[0] = NULL;
+
+ LV2URIMap* controller = new LV2URIMap();
+ add_feature(LV2_URI_MAP_URI, controller->feature(), controller);
+}
+
+
+const LV2Features::Feature*
+LV2Features::feature(const std::string& uri)
+{
+ Features::const_iterator i = _features.find(uri);
+ if (i != _features.end())
+ return &i->second;
+ else
+ return NULL;
+}
+
+
+void
+LV2Features::add_feature(const std::string& uri, LV2_Feature* feature, void* controller)
+{
+#ifndef NDEBUG
+ Features::const_iterator i = _features.find(uri);
+ assert(i == _features.end());
+ assert(_lv2_features[_features.size()] == NULL);
+#endif
+ _features.insert(make_pair(uri, Feature(feature, controller)));
+
+ _lv2_features = (LV2_Feature**)realloc(_lv2_features, sizeof(LV2_Feature*) * (_features.size() + 1));
+ _lv2_features[_features.size()-1] = feature;
+ _lv2_features[_features.size()] = NULL;
+}
+
+
+} // namespace Shared
+} // namespace Ingen
diff --git a/src/shared/LV2Features.hpp b/src/shared/LV2Features.hpp
new file mode 100644
index 00000000..3a174aa2
--- /dev/null
+++ b/src/shared/LV2Features.hpp
@@ -0,0 +1,63 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LV2FEATURES_HPP
+#define LV2FEATURES_HPP
+
+#include CONFIG_H_PATH
+#ifndef HAVE_SLV2
+#error "This file requires SLV2, but HAVE_SLV2 is not defined. Please report."
+#endif
+
+#include <map>
+#include <string>
+#include <slv2/slv2.h>
+
+namespace Ingen {
+namespace Shared {
+
+
+/** Stuff that may need to be passed to an LV2 plugin (i.e. LV2 features).
+ */
+class LV2Features {
+public:
+ LV2Features();
+
+ struct Feature {
+ Feature(LV2_Feature* f, void* c=NULL) : feature(f), controller(c) {}
+ LV2_Feature* feature; ///< LV2 feature struct (plugin exposed)
+ void* controller; ///< Ingen internals, not exposed to plugin
+ };
+
+ typedef std::map<std::string, Feature> Features;
+
+ const Feature* feature(const std::string& uri);
+
+ void add_feature(const std::string& uri, LV2_Feature* feature, void* controller);
+
+ LV2_Feature** lv2_features() const { return _lv2_features; }
+
+private:
+ Features _features;
+ LV2_Feature** _lv2_features;
+};
+
+
+} // namespace Shared
+} // namespace Ingen
+
+#endif // LV2FEATURES_HPP
diff --git a/src/shared/LV2URIMap.cpp b/src/shared/LV2URIMap.cpp
new file mode 100644
index 00000000..c01dfea0
--- /dev/null
+++ b/src/shared/LV2URIMap.cpp
@@ -0,0 +1,75 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define __STDC_LIMIT_MACROS 1
+#include <cassert>
+#include <iostream>
+#include <stdint.h>
+#include "LV2URIMap.hpp"
+
+using namespace std;
+
+namespace Ingen {
+namespace Shared {
+
+
+LV2URIMap::LV2URIMap()
+ : next_uri_id(1)
+{
+ uri_map_feature_data.uri_to_id = &LV2URIMap::uri_map_uri_to_id;
+ uri_map_feature_data.callback_data = this;
+ uri_map_feature.URI = LV2_URI_MAP_URI;
+ uri_map_feature.data = &uri_map_feature_data;
+}
+
+
+uint32_t
+LV2URIMap::uri_to_id(const char* map,
+ const char* uri)
+{
+ return uri_map_uri_to_id(this, map, uri);
+}
+
+
+uint32_t
+LV2URIMap::uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data,
+ const char* map,
+ const char* uri)
+{
+ // TODO: map ignored, < UINT16_MAX assumed
+
+ LV2URIMap* me = (LV2URIMap*)callback_data;
+ uint32_t ret = 0;
+
+ URIMap::iterator i = me->uri_map.find(uri);
+ if (i != me->uri_map.end()) {
+ ret = i->second;
+ } else {
+ ret = me->next_uri_id++;
+ me->uri_map.insert(make_pair(string(uri), ret));
+ }
+
+ /*cout << "URI MAP (" << (map ? (void*)map : NULL)
+ << "): " << uri << " -> " << ret << endl;*/
+
+ assert(ret <= UINT16_MAX);
+ return ret;
+}
+
+
+} // namespace Shared
+} // namespace Ingen
diff --git a/src/shared/LV2URIMap.hpp b/src/shared/LV2URIMap.hpp
new file mode 100644
index 00000000..35130066
--- /dev/null
+++ b/src/shared/LV2URIMap.hpp
@@ -0,0 +1,64 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LV2URIMAP_HPP
+#define LV2URIMAP_HPP
+
+#include CONFIG_H_PATH
+#ifndef HAVE_SLV2
+#error "This file requires SLV2, but HAVE_SLV2 is not defined. Please report."
+#endif
+
+#include <map>
+#include <string>
+#include <boost/utility.hpp>
+#include <slv2/slv2.h>
+#include "common/lv2ext/lv2_uri_map.h"
+
+namespace Ingen {
+namespace Shared {
+
+
+/** Implementation of the LV2 URI Map extension
+ */
+class LV2URIMap : public boost::noncopyable {
+public:
+ LV2URIMap();
+
+ LV2_Feature* feature() { return &uri_map_feature; }
+
+ uint32_t uri_to_id(const char* map,
+ const char* uri);
+
+private:
+ typedef std::map<std::string, uint32_t> URIMap;
+
+ static uint32_t uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data,
+ const char* map,
+ const char* uri);
+
+ LV2_Feature uri_map_feature;
+ LV2_URI_Map_Feature uri_map_feature_data;
+ URIMap uri_map;
+ uint32_t next_uri_id;
+};
+
+
+} // namespace Shared
+} // namespace Ingen
+
+#endif // LV2URIMAP_HPP
diff --git a/src/shared/Makefile.am b/src/shared/Makefile.am
new file mode 100644
index 00000000..c26c98a2
--- /dev/null
+++ b/src/shared/Makefile.am
@@ -0,0 +1,22 @@
+noinst_LTLIBRARIES = libingen_shared.la
+
+libingen_shared_la_CXXFLAGS = \
+ @GLIBMM_CFLAGS@ \
+ @INGEN_CFLAGS@ \
+ @RAUL_CFLAGS@ \
+ @REDLANDMM_CFLAGS@ \
+ @SLV2_CFLAGS@
+
+libingen_shared_la_SOURCES = \
+ Builder.cpp \
+ Builder.hpp \
+ ClashAvoider.cpp \
+ ClashAvoider.hpp \
+ LV2Features.cpp \
+ LV2Features.hpp \
+ LV2URIMap.cpp \
+ LV2URIMap.hpp \
+ OSCSender.cpp \
+ OSCSender.hpp \
+ Store.cpp \
+ Store.hpp
diff --git a/src/shared/OSCSender.cpp b/src/shared/OSCSender.cpp
new file mode 100644
index 00000000..f366b1a4
--- /dev/null
+++ b/src/shared/OSCSender.cpp
@@ -0,0 +1,125 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "OSCSender.hpp"
+#include <cassert>
+#include <iostream>
+#include <unistd.h>
+
+using namespace std;
+
+namespace Ingen {
+namespace Shared {
+
+
+OSCSender::OSCSender()
+ : _transfer(NULL)
+ , _address(NULL)
+ , _enabled(true)
+{
+}
+
+
+void
+OSCSender::bundle_begin()
+{
+ assert(!_transfer);
+ lo_timetag t;
+ lo_timetag_now(&t);
+ _transfer = lo_bundle_new(t);
+ _send_state = SendingBundle;
+}
+
+
+void
+OSCSender::bundle_end()
+{
+ transfer_end();
+}
+
+
+void
+OSCSender::transfer_begin()
+{
+ assert(!_transfer);
+ lo_timetag t;
+ lo_timetag_now(&t);
+ _transfer = lo_bundle_new(t);
+ _send_state = SendingTransfer;
+}
+
+
+void
+OSCSender::transfer_end()
+{
+ assert(_transfer);
+ lo_send_bundle(_address, _transfer);
+ lo_bundle_free(_transfer);
+ _transfer = NULL;
+ _send_state = Immediate;
+}
+
+
+int
+OSCSender::send(const char *path, const char *types, ...)
+{
+ if (!_enabled)
+ return 0;
+
+ va_list args;
+ va_start(args, types);
+
+ lo_message msg = lo_message_new();
+ int ret = lo_message_add_varargs(msg, types, args);
+
+ if (!ret)
+ send_message(path, msg);
+
+ va_end(args);
+
+ return ret;
+}
+
+
+void
+OSCSender::send_message(const char* path, lo_message msg)
+{
+ // FIXME: size? liblo doesn't export this.
+ // Don't want to exceed max UDP packet size (good default value?)
+ static const size_t MAX_BUNDLE_SIZE = 1024;
+
+ if (!_enabled)
+ return;
+
+ if (_transfer) {
+ if (lo_bundle_length(_transfer) + lo_message_length(msg, path) > MAX_BUNDLE_SIZE) {
+ if (_send_state == SendingBundle)
+ cerr << "WARNING: Maximum bundle size reached, bundle split" << endl;
+ lo_send_bundle(_address, _transfer);
+ lo_timetag t;
+ lo_timetag_now(&t);
+ _transfer = lo_bundle_new(t);
+ }
+ lo_bundle_add_message(_transfer, path, msg);
+
+ } else {
+ lo_send_message(_address, path, msg);
+ }
+}
+
+} // namespace Shared
+} // namespace Ingen
diff --git a/src/shared/OSCSender.hpp b/src/shared/OSCSender.hpp
new file mode 100644
index 00000000..da91caed
--- /dev/null
+++ b/src/shared/OSCSender.hpp
@@ -0,0 +1,59 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef OSCSENDER_H
+#define OSCSENDER_H
+
+#include <inttypes.h>
+#include <lo/lo.h>
+
+namespace Ingen {
+namespace Shared {
+
+class OSCSender {
+public:
+ OSCSender();
+ virtual ~OSCSender() {}
+
+ lo_address address() const { return _address; }
+
+ // Message bundling
+ void bundle_begin();
+ void bundle_end();
+
+ // Transfers (loose bundling)
+ void transfer_begin();
+ void transfer_end();
+
+protected:
+ int send(const char *path, const char *types, ...);
+ void send_message(const char* path, lo_message m);
+
+ enum SendState { Immediate, SendingBundle, SendingTransfer };
+
+ SendState _send_state;
+ lo_bundle _transfer;
+ lo_address _address;
+ bool _enabled;
+};
+
+
+} // namespace Shared
+} // namespace Ingen
+
+#endif // OSCSENDER_H
+
diff --git a/src/shared/Store.cpp b/src/shared/Store.cpp
new file mode 100644
index 00000000..9f0f3624
--- /dev/null
+++ b/src/shared/Store.cpp
@@ -0,0 +1,108 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <raul/PathTable.hpp>
+#include <raul/TableImpl.hpp>
+#include "common/interface/Node.hpp"
+#include "common/interface/Port.hpp"
+#include "Store.hpp"
+
+using namespace std;
+using namespace Raul;
+
+namespace Ingen {
+namespace Shared {
+
+
+void
+Store::add(GraphObject* o)
+{
+ if (find(o->path()) != end()) {
+ cerr << "[Store] ERROR: Attempt to add duplicate object " << o->path() << endl;
+ return;
+ }
+
+ insert(make_pair(o->path(), o));
+
+ Node* node = dynamic_cast<Node*>(o);
+ if (node) {
+ for (uint32_t i=0; i < node->num_ports(); ++i) {
+ add(node->port(i));
+ }
+ }
+}
+
+
+Store::const_iterator
+Store::children_begin(SharedPtr<Shared::GraphObject> o) const
+{
+ const_iterator parent = find(o->path());
+ assert(parent != end());
+ ++parent;
+ return parent;
+}
+
+
+Store::const_iterator
+Store::children_end(SharedPtr<Shared::GraphObject> o) const
+{
+ const_iterator parent = find(o->path());
+ assert(parent != end());
+ return find_descendants_end(parent);
+}
+
+
+SharedPtr<Shared::GraphObject>
+Store::find_child(SharedPtr<Shared::GraphObject> parent, const string& child_name) const
+{
+ const_iterator pi = find(parent->path());
+ assert(pi != end());
+ const_iterator children_end = find_descendants_end(pi);
+ const_iterator child = find(pi, children_end, parent->path().base() + child_name);
+ if (child != end())
+ return child->second;
+ else
+ return SharedPtr<Shared::GraphObject>();
+}
+
+
+unsigned
+Store::child_name_offset(const Raul::Path& parent,
+ const Raul::Symbol& symbol,
+ bool allow_zero)
+{
+ unsigned offset = 0;
+
+ while (true) {
+ std::stringstream ss;
+ ss << symbol;
+ if (offset > 0)
+ ss << "_" << offset;
+ if (find(parent.base() + ss.str()) == end() && (allow_zero || offset > 0))
+ break;
+ else if (offset == 0)
+ offset = 2;
+ else
+ ++offset;
+ }
+
+ return offset;
+}
+
+
+} // namespace Shared
+} // namespace Ingen
diff --git a/src/shared/Store.hpp b/src/shared/Store.hpp
new file mode 100644
index 00000000..27754345
--- /dev/null
+++ b/src/shared/Store.hpp
@@ -0,0 +1,60 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef COMMON_STORE_H
+#define COMMON_STORE_H
+
+#include <string>
+#include <glibmm/thread.h>
+#include <raul/PathTable.hpp>
+#include "interface/GraphObject.hpp"
+
+using Raul::PathTable;
+
+namespace Ingen {
+namespace Shared {
+
+
+class Store : public Raul::PathTable< SharedPtr<Shared::GraphObject> > {
+public:
+ virtual ~Store() {}
+
+ virtual void add(Shared::GraphObject* o);
+
+ typedef Raul::Table< Raul::Path, SharedPtr<Shared::GraphObject> > Objects;
+
+ const_iterator children_begin(SharedPtr<Shared::GraphObject> o) const;
+ const_iterator children_end(SharedPtr<Shared::GraphObject> o) const;
+
+ SharedPtr<Shared::GraphObject> find_child(SharedPtr<Shared::GraphObject> parent,
+ const std::string& child_name) const;
+
+ unsigned child_name_offset(const Raul::Path& parent,
+ const Raul::Symbol& symbol,
+ bool allow_zero=true);
+
+ Glib::RWLock& lock() { return _lock; }
+
+private:
+ Glib::RWLock _lock;
+};
+
+
+} // namespace Shared
+} // namespace Ingen
+
+#endif // COMMON_STORE_H
diff --git a/src/shared/wscript b/src/shared/wscript
new file mode 100644
index 00000000..1974a827
--- /dev/null
+++ b/src/shared/wscript
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+import Params
+
+def build(bld):
+ obj = bld.create_obj('cpp', 'shlib')
+ obj.source = '''
+ Builder.cpp
+ ClashAvoider.cpp
+ LV2Features.cpp
+ LV2URIMap.cpp
+ OSCSender.cpp
+ Store.cpp
+ '''
+ obj.includes = ['..', '../../common', '../..']
+ obj.name = 'libingen_shared'
+ obj.target = 'ingen_shared'
+ obj.uselib = 'GLIBMM SLV2 RAUL REDLANDMM'
+ obj.vnum = '0.0.0'
+