aboutsummaryrefslogtreecommitdiffstats
path: root/src/Machine.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-02-05 06:23:05 +0000
committerDavid Robillard <d@drobilla.net>2007-02-05 06:23:05 +0000
commit4c8aad127d9504c7d355975180f877f5baa9f744 (patch)
treebdb70b9a849a290f32c9bbb45947da4b796dcd97 /src/Machine.cpp
parent60647fedf17cdebfcf45c76d8fa9cee120006921 (diff)
downloadmachina-4c8aad127d9504c7d355975180f877f5baa9f744.tar.gz
machina-4c8aad127d9504c7d355975180f877f5baa9f744.tar.bz2
machina-4c8aad127d9504c7d355975180f877f5baa9f744.zip
It's aliiiiivee!
git-svn-id: http://svn.drobilla.net/lad/machina@278 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/Machine.cpp')
-rw-r--r--src/Machine.cpp127
1 files changed, 104 insertions, 23 deletions
diff --git a/src/Machine.cpp b/src/Machine.cpp
index 246db73..a6e63d3 100644
--- a/src/Machine.cpp
+++ b/src/Machine.cpp
@@ -22,15 +22,11 @@
namespace Machina {
-Machine::Machine(size_t poly)
- : _activated(false)
- , _initial_node(new Node())
- , _voices(poly, NULL)//_initial_node)
+Machine::Machine()
+ : _is_activated(false)
+ , _is_finished(false)
, _time(0)
{
- /* reserve poly spaces in _voices, so accessing it
- * with operator[] should be realtime safe.
- */
}
@@ -40,39 +36,122 @@ Machine::~Machine()
void
+Machine::add_node(SharedPtr<Node> node)
+{
+ assert(!_is_activated);
+
+ _nodes.push_back(node);
+}
+
+
+/** Exit all active states and reset time to 0.
+ */
+void
Machine::reset()
{
- assert(!_activated);
+ if (!_is_finished) {
+ for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) {
+ const SharedPtr<Node> node = (*n);
+
+ if (node->is_active())
+ node->exit(_time);
+ }
+ }
+
+ _time = 0;
+ _is_finished = false;
+}
- for (std::vector<Node*>::iterator i = _voices.begin();
- i != _voices.end(); ++i) {
- *i = NULL;
+
+/** Return the active Node with the earliest exit time.
+ */
+SharedPtr<Node>
+Machine::earliest_node() const
+{
+ SharedPtr<Node> earliest;
+
+ for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) {
+ const SharedPtr<Node> node = (*n);
+
+ if (node->is_active())
+ if (!earliest || node->exit_time() < earliest->exit_time())
+ earliest = node;
}
+
+ return earliest;
}
+/** Exit an active node at the current _time.
+ */
void
-Machine::add_node(const Node::ID& id, SharedPtr<Node> node)
+Machine::exit_node(const SharedPtr<Node> node)
{
- assert(!_activated);
- _nodes[id] = node;
+ node->exit(_time);
+
+ // Activate all successors to this node
+ // (that aren't aready active right now)
+ for (Node::EdgeList::const_iterator s = node->outgoing_edges().begin();
+ s != node->outgoing_edges().end(); ++s) {
+ SharedPtr<Node> dst = (*s)->dst();
+
+ if (!dst->is_active())
+ dst->enter(_time);
+
+ }
}
-void
-Machine::process(FrameCount nframes)
+/** Run the machine for @a nframes frames.
+ *
+ * Returns false when the machine has finished running (i.e. there are
+ * no currently active states).
+ *
+ * If this returns false, time() will return the exact time stamp the
+ * machine actually finished on (so it can be restarted immediately
+ * with sample accuracy if necessary).
+ */
+bool
+Machine::run(FrameCount nframes)
{
- const FrameCount cycle_end = _time + nframes;
- bool done = false;
+ if (_is_finished)
+ return false;
- assert(_activated);
+ const FrameCount cycle_end = _time + nframes;
- FrameCount latest_event = _time;
+ assert(_is_activated);
- std::cerr << "--------- " << _time << " - " << _time + nframes << std::endl;
+ //std::cerr << "--------- " << _time << " - " << _time + nframes << std::endl;
- // FIXME: way too much iteration
+ // Initial run, enter all initial states
+ if (_time == 0)
+ for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n)
+ if ((*n)->is_initial())
+ (*n)->enter(0);
+ while (true) {
+
+ SharedPtr<Node> earliest = earliest_node();
+
+ // No more active states, machine is finished
+ if (!earliest) {
+ _is_finished = true;
+ return false;
+
+ // Earliest active state ends this cycle
+ } else if (earliest->exit_time() < cycle_end) {
+ _time = earliest->exit_time();
+ exit_node(earliest);
+
+ // Earliest active state ends in the future, done this cycle
+ } else {
+ _time = cycle_end;
+ return true;
+ }
+
+ }
+
+#if 0
while (!done) {
done = true;
@@ -130,8 +209,10 @@ Machine::process(FrameCount nframes)
}
}
}
-
_time += nframes;
+
+ return false;
+#endif
}