diff options
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/Builder.cpp | 98 | ||||
-rw-r--r-- | src/shared/Builder.hpp | 57 | ||||
-rw-r--r-- | src/shared/ClashAvoider.cpp | 214 | ||||
-rw-r--r-- | src/shared/ClashAvoider.hpp | 108 | ||||
-rw-r--r-- | src/shared/LV2Features.cpp | 66 | ||||
-rw-r--r-- | src/shared/LV2Features.hpp | 63 | ||||
-rw-r--r-- | src/shared/LV2URIMap.cpp | 75 | ||||
-rw-r--r-- | src/shared/LV2URIMap.hpp | 64 | ||||
-rw-r--r-- | src/shared/Makefile.am | 22 | ||||
-rw-r--r-- | src/shared/OSCSender.cpp | 125 | ||||
-rw-r--r-- | src/shared/OSCSender.hpp | 59 | ||||
-rw-r--r-- | src/shared/Store.cpp | 108 | ||||
-rw-r--r-- | src/shared/Store.hpp | 60 | ||||
-rw-r--r-- | src/shared/wscript | 19 |
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' + |