Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

add [flow.trigger] (and forgotten [flow.pack]

  • Loading branch information...
commit df5bc8999b87869d25e0b2dbb4f0e1c0a1b01ae3 1 parent dd7d1ad
@aalex authored
View
28 examples/trigger.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<tempi version="0.1.9">
+ <graph>
+ <node id="loadmess0" class="base.loadmess">
+ <attribute name="value"><s>hello</s><i>2</i><f>3.14159</f></attribute>
+ </node>
+ <node id="trigger0" class="flow.trigger">
+ <attribute name="types"><s>baba</s></attribute>
+ </node>
+ <node id="print0" class="base.print">
+ <attribute name="prefix"><s>0th: </s></attribute>
+ </node>
+ <node id="print1" class="base.print">
+ <attribute name="prefix"><s>1th: </s></attribute>
+ </node>
+ <node id="print2" class="base.print">
+ <attribute name="prefix"><s>2th: </s></attribute>
+ </node>
+ <node id="print3" class="base.print">
+ <attribute name="prefix"><s>3rd </s></attribute>
+ </node>
+ <connection from="loadmess0" outlet="0" to="trigger0" inlet="input"/>
+ <connection from="trigger0" outlet="0" to="print0" inlet="0"/>
+ <connection from="trigger0" outlet="1" to="print1" inlet="0"/>
+ <connection from="trigger0" outlet="2" to="print2" inlet="0"/>
+ <connection from="trigger0" outlet="3" to="print3" inlet="0"/>
+ </graph>
+</tempi>
View
2  plugins-base/Makefile.am
@@ -62,6 +62,7 @@ libtempi_plugins_base_la_SOURCES = \
flow/print_node.cpp \
flow/routenode.cpp \
flow/spigotnode.cpp \
+ flow/triggernode.cpp \
flow/unpacknode.cpp \
mapping/filter.cpp \
mapping/slide.cpp \
@@ -106,6 +107,7 @@ EXTRA_DIST = \
flow/print_node.h \
flow/routenode.h \
flow/spigotnode.h \
+ flow/triggernode.h \
flow/unpacknode.h \
mapping/average.h \
mapping/filter.h \
View
2  plugins-base/baselibrary.cpp
@@ -34,6 +34,7 @@
#include "plugins-base/flow/prependnode.h"
#include "plugins-base/flow/print_node.h"
#include "plugins-base/flow/routenode.h"
+#include "plugins-base/flow/triggernode.h"
#include "plugins-base/flow/unpacknode.h"
#include "plugins-base/spatosc/spatoscnode.h"
#include "plugins-base/flow/spigotnode.h"
@@ -83,6 +84,7 @@ void BaseLibrary::load(NodeFactory &factory, const char *prefix) const
factory.registerTypeT<SpigotNode>(concatenate("base.", "spigot").c_str());
factory.registerTypeT<PrependNode>(concatenate("base.", "prepend").c_str());
factory.registerTypeT<RouteNode>(concatenate("base.", "route").c_str());
+ factory.registerTypeT<TriggerNode>(concatenate("flow.", "trigger").c_str());
factory.registerTypeT<UnpackNode>(concatenate("flow.", "unpack").c_str());
factory.registerTypeT<LineNode>(concatenate("flow.", "line").c_str());
factory.registerTypeT<LoadMessNode>(concatenate("base.", "loadmess").c_str());
View
145 plugins-base/flow/packnode.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2011 Alexandre Quessy
+ * Copyright (C) 2011 Michal Seta
+ * Copyright (C) 2012 Nicolas Bouillot
+ *
+ * This file is part of Tempi.
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tempi 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 more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tempi. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <iostream>
+#include "plugins-base/flow/packnode.h"
+#include "tempi/utils.h"
+#include "tempi/log.h"
+
+namespace tempi {
+namespace plugins_base {
+
+const char * const PackNode::RESULT_OUTLET = "result";
+const char * const PackNode::NUM_ATTR = "number";
+const char * const PackNode::ALL_HOT_ATTR = "all-hot";
+
+PackNode::PackNode() :
+ Node()
+{
+ addAttribute(Attribute::ptr(new Attribute(NUM_ATTR, Message("u", 0), "Number of atoms to pack together. The object creates as many inlets numbered from 0 to n-1.")));
+ addAttribute(Attribute::ptr(new Attribute(ALL_HOT_ATTR, Message("b", false), "If true, makes all inlets hot. (output the results when a message is received.")));
+ Logger::log(DEBUG, "[pack] constructor: = (u:0");
+ addOutlet(RESULT_OUTLET, "Resulting packed message goes here.");
+ setShortDocumentation("Combines several atoms into one message.");
+}
+
+void PackNode::processMessage(const char *inlet, const Message &message)
+{
+ bool is_a_packing_inlet = false;
+ unsigned int current_number_of_inlets =
+ this->getAttributeValue(NUM_ATTR).getUnsignedInt(0);
+ bool all_hot = this->getAttributeValue(ALL_HOT_ATTR).getBoolean(0);
+ for (int i = 0; i < (unsigned int) current_number_of_inlets; ++i)
+ {
+ std::ostringstream name_os;
+ name_os << i;
+ if (utils::stringsMatch(inlet, name_os.str().c_str()))
+ {
+ is_a_packing_inlet = true;
+ stored_messages_[i] = message;
+ if (i == 0 || all_hot)
+ this->outputResult();
+ break;
+ }
+ }
+}
+
+void PackNode::outputResult()
+{
+ Message ret;
+ unsigned int current_number_of_inlets =
+ this->getAttributeValue(NUM_ATTR).getUnsignedInt(0);
+ for (unsigned int i = current_number_of_inlets; i >= 0; --i)
+ {
+ std::ostringstream name_os;
+ name_os << i;
+ ret.prependMessage(stored_messages_[i]);
+ // TODO: implement appendMessage
+ if (i == 0)
+ break; // IMPORTANT
+ }
+ output(RESULT_OUTLET, ret);
+}
+
+void PackNode::printInletsInfo() const
+{
+ std::ostringstream os;
+ os << "[pack]: actual inlets:";
+ std::vector<std::string> inlets = this->listInlets();
+ std::vector<std::string>::const_iterator iter;
+ for (iter = inlets.begin(); iter != inlets.end(); ++iter)
+ os << " " << (*iter);
+ Logger::log(DEBUG, os.str().c_str());
+}
+
+bool PackNode::onNodeAttributeChanged(const char *name, const Message &value)
+{
+ if (! utils::stringsMatch(NUM_ATTR, name))
+ return true; // true means it's OK to change that attribute
+ {
+ std::ostringstream os;
+ os << "[pack] " << __FUNCTION__ << ": name=\"" << name << "\" value=" << value;
+ Logger::log(DEBUG, os);
+ }
+ this->printInletsInfo();
+
+ unsigned int new_size = value.getUnsignedInt(0);
+ unsigned int current_number_of_inlets =
+ this->getAttributeValue(NUM_ATTR).getUnsignedInt(0);
+ if (new_size > current_number_of_inlets)
+ {
+ Message empty;
+ for (unsigned int i = current_number_of_inlets; i < new_size; ++i)
+ {
+ std::ostringstream name_os;
+ name_os << i;
+ std::ostringstream doc;
+ doc << "Input for the " << i << "th message to pack together with the other ones.";
+ {
+ std::ostringstream os;
+ os << "[pack] " << __FUNCTION__ << ": add inlet " << i;
+ Logger::log(INFO, os);
+ }
+ addInlet(name_os.str().c_str(), doc.str().c_str());
+ stored_messages_.push_back(empty);
+ }
+ }
+ else if (new_size < current_number_of_inlets)
+ {
+ for (unsigned int i = new_size; i < current_number_of_inlets; ++i)
+ {
+ std::ostringstream name_os;
+ name_os << i;
+ {
+ std::ostringstream os;
+ os << "[pack] " << __FUNCTION__ << ": remove inlet " << i;
+ Logger::log(INFO, os);
+ }
+ removeInlet(name_os.str().c_str());
+ }
+ stored_messages_.erase(stored_messages_.begin() + new_size, stored_messages_.end());
+ }
+ this->printInletsInfo();
+ return true;
+}
+
+} // end of namespace
+} // end of namespace
+
View
58 plugins-base/flow/packnode.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011 Alexandre Quessy
+ * Copyright (C) 2011 Michal Seta
+ * Copyright (C) 2012 Nicolas Bouillot
+ *
+ * This file is part of Tempi.
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tempi 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 more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tempi. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file
+ * The PackNode class.
+ */
+#ifndef __TEMPI_BASE_PACK_NODE_H__
+#define __TEMPI_BASE_PACK_NODE_H__
+
+#include "tempi/node.h"
+#include <vector>
+#include <string>
+
+namespace tempi {
+namespace plugins_base {
+
+/**
+ * Combines several atoms into a message.
+ */
+class PackNode : public Node
+{
+ public:
+ PackNode();
+ protected:
+ virtual void processMessage(const char *inlet, const Message &message);
+ virtual bool onNodeAttributeChanged(const char *name, const Message &value);
+ private:
+ void printInletsInfo() const;
+ std::vector<Message> stored_messages_;
+ void outputResult();
+ static const char * const RESULT_OUTLET;
+ static const char * const NUM_ATTR;
+ static const char * const ALL_HOT_ATTR;
+};
+
+} // end of namespace
+} // end of namespace
+
+#endif // ifndef
+
View
143 plugins-base/flow/triggernode.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2011 Alexandre Quessy
+ * Copyright (C) 2011 Michal Seta
+ * Copyright (C) 2012 Nicolas Bouillot
+ *
+ * This file is part of Tempi.
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tempi 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 more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tempi. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <iostream>
+#include "plugins-base/flow/triggernode.h"
+#include "tempi/utils.h"
+#include "tempi/log.h"
+
+namespace tempi {
+namespace plugins_base {
+
+const char * const TriggerNode::INPUT_INLET = "input";
+const char * const TriggerNode::TYPES_ATTR = "types";
+
+TriggerNode::TriggerNode() :
+ Node()
+{
+ addAttribute(Attribute::ptr(new Attribute(TYPES_ATTR, Message("s", ""), "List of types to output. \"a\" means anythings, which forwards the incoming message. \"b\": is for bang: an empty message.")));
+ Logger::log(DEBUG, "[trigger] constructor: types = (s:\"\")");
+ addInlet(INPUT_INLET, "Incoming messages go here.");
+ setShortDocumentation("Sequences messages in right-to-left order and converts messages to empty one, if needed.");
+}
+
+void TriggerNode::processMessage(const char *inlet, const Message &message)
+{
+ if (! utils::stringsMatch(inlet, INPUT_INLET))
+ return;
+ std::string types = this->getAttributeValue(TYPES_ATTR).getString(0);
+ {
+ std::ostringstream os;
+ os << "[trigger]: current types are " << types;
+ Logger::log(INFO, os);
+ }
+ Message empty;
+ for (int i = (int) types.size() - 1; i >= 0; --i)
+ {
+ // output last atom first. (to last outlet)
+ bool is_bang = types[(unsigned int) i] == 'b';
+ {
+ std::ostringstream os;
+ os << "[trigger] " << __FUNCTION__ << ": output ";
+ if (is_bang)
+ os << empty;
+ else
+ os << message;
+ os << " to " << i << "th outlet.";
+ Logger::log(INFO, os);
+ }
+ std::ostringstream name_os;
+ name_os << i;
+ if (is_bang)
+ output(name_os.str().c_str(), empty);
+ else
+ output(name_os.str().c_str(), message);
+ }
+}
+
+void TriggerNode::printOutletsInfo() const
+{
+ {
+ std::ostringstream os;
+ os << "[trigger]: actual outlets:";
+ std::vector<std::string> outlets = this->listOutlets();
+ std::vector<std::string>::const_iterator iter;
+ for (iter = outlets.begin(); iter != outlets.end(); ++iter)
+ os << " " << (*iter);
+ Logger::log(DEBUG, os);
+ }
+}
+
+bool TriggerNode::onNodeAttributeChanged(const char *name, const Message &value)
+{
+ std::string types = value.getString(0);
+ int new_size = (int) types.size();
+ for (int i = 0; i < new_size; ++i)
+ {
+ char c = types[(unsigned int) i];
+ if (c != 'b' && c != 'a')
+ {
+ std::ostringstream os;
+ os << "[trigger] " << __FUNCTION__ << ": Invalid types: " << value;
+ Logger::log(ERROR, os);
+ return false;
+ }
+ }
+ this->printOutletsInfo();
+
+ int current_number_of_outlets = (int) this->getAttributeValue(TYPES_ATTR).getString(0).size();
+
+ if (new_size > current_number_of_outlets)
+ {
+ for (int i = current_number_of_outlets; i < new_size; ++i)
+ {
+ std::ostringstream name_os;
+ name_os << i;
+ std::ostringstream doc;
+ doc << "Output number " << i;
+ {
+ std::ostringstream os;
+ os << "[trigger] " << __FUNCTION__ << ": add outlet " << i;
+ Logger::log(INFO, os);
+ }
+ addOutlet(name_os.str().c_str(), doc.str().c_str());
+ }
+ }
+ else if (new_size < current_number_of_outlets)
+ {
+ for (int i = new_size; i < current_number_of_outlets; ++i)
+ {
+ std::ostringstream name_os;
+ name_os << i;
+ {
+ std::ostringstream os;
+ os << "[trigger] " << __FUNCTION__ << ": remove outlet " << i;
+ Logger::log(INFO, os);
+ }
+ removeOutlet(name_os.str().c_str());
+ }
+ }
+ this->printOutletsInfo();
+ return true;
+}
+
+} // end of namespace
+} // end of namespace
+
View
55 plugins-base/flow/triggernode.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 Alexandre Quessy
+ * Copyright (C) 2011 Michal Seta
+ * Copyright (C) 2012 Nicolas Bouillot
+ *
+ * This file is part of Tempi.
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tempi 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 more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tempi. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file
+ * The TriggerNode class.
+ */
+#ifndef __TEMPI_BASE_TRIGGER_NODE_H__
+#define __TEMPI_BASE_TRIGGER_NODE_H__
+
+#include "tempi/node.h"
+#include <vector>
+#include <string>
+
+namespace tempi {
+namespace plugins_base {
+
+/**
+ * Splits a message into atoms.
+ */
+class TriggerNode : public Node
+{
+ public:
+ TriggerNode();
+ protected:
+ virtual void processMessage(const char *inlet, const Message &message);
+ virtual bool onNodeAttributeChanged(const char *name, const Message &value);
+ private:
+ void printOutletsInfo() const;
+ static const char * const INPUT_INLET;
+ static const char * const TYPES_ATTR;
+};
+
+} // end of namespace
+} // end of namespace
+
+#endif // ifndef
+
Please sign in to comment.
Something went wrong with that request. Please try again.