diff options
-rw-r--r-- | src/engine/Engine.cpp | 5 | ||||
-rw-r--r-- | src/engine/Machine.cpp | 56 | ||||
-rw-r--r-- | src/engine/machina/Machine.hpp | 7 |
3 files changed, 60 insertions, 8 deletions
diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index fede33f..2b4088e 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -30,11 +30,16 @@ namespace Machina { SharedPtr<Machine> Engine::load_machine(const Glib::ustring& uri) { + SharedPtr<Machine> old_machine = _driver->machine(); // Hold a reference to current machine.. + SharedPtr<Machine> m = Loader().load(uri); if (m) { m->activate(); _driver->set_machine(m); } + + // .. and drop it in this thread (to prevent deallocation in the RT thread) + return m; } diff --git a/src/engine/Machine.cpp b/src/engine/Machine.cpp index 844d2ce..f2aa845 100644 --- a/src/engine/Machine.cpp +++ b/src/engine/Machine.cpp @@ -85,24 +85,68 @@ Machine::earliest_node() const { SharedPtr<Node> earliest; - for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) { + for (size_t i=0; i < MAX_ACTIVE_NODES; ++i) { + const SharedPtr<Node> node = _active_nodes[i]; + + if (node) { + assert(node->is_active()); + if (!earliest || node->exit_time() < earliest->exit_time()) { + earliest = node; + } + } + } + /*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; } +/** Enter a state at the current _time. + * + * Returns true if node was entered, or false if the maximum active nodes has been reached. + */ +bool +Machine::enter_node(const SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node> node) +{ + assert(!node->is_active()); + + /* FIXME: Would be best to use the MIDI note here as a hash key, at least + * while all actions are still MIDI notes... */ + size_t index = (rand() % MAX_ACTIVE_NODES); + for (size_t i=0; i < MAX_ACTIVE_NODES; ++i) { + if (_active_nodes[index] == NULL) { + node->enter(sink, _time); + assert(node->is_active()); + _active_nodes[index] = node; + return true; + } + index = (index + 1) % MAX_ACTIVE_NODES; + } + + // If we get here, ran out of active node spots. Don't enter node + return false; +} + + + /** Exit an active node at the current _time. */ void Machine::exit_node(SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node> node) { node->exit(sink, _time); + assert(!node->is_active()); + for (size_t i=0; i < MAX_ACTIVE_NODES; ++i) { + if (_active_nodes[i] == node) { + _active_nodes[i].reset(); + } + } // Activate all successors to this node // (that aren't aready active right now) @@ -115,9 +159,8 @@ Machine::exit_node(SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node> node) SharedPtr<Node> dst = (*s)->dst(); if (!dst->is_active()) - dst->enter(sink, _time); + enter_node(sink, dst); } - } } @@ -125,6 +168,7 @@ Machine::exit_node(SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node> node) /** Run the machine for @a nframes frames. * * Returns the duration of time the machine actually ran (from 0 to nframes). + * * Caller can check is_finished() to determine if the machine still has any * active states. If not, time() will return the exact time stamp the * machine actually finished on (so it can be restarted immediately @@ -156,8 +200,8 @@ Machine::run(const Raul::TimeSlice& time) assert( ! (*n)->is_active()); if ((*n)->is_initial()) { - (*n)->enter(sink, 0); - entered = true; + if (enter_node(sink, (*n))) + entered = true; } } diff --git a/src/engine/machina/Machine.hpp b/src/engine/machina/Machine.hpp index fb37f4e..b8e371d 100644 --- a/src/engine/machina/Machine.hpp +++ b/src/engine/machina/Machine.hpp @@ -68,7 +68,11 @@ private: // Audio context SharedPtr<Node> earliest_node() const; - void exit_node(const SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node>); + bool enter_node(const SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node> node); + void exit_node(const SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node>); + + static const size_t MAX_ACTIVE_NODES = 128; + SharedPtr<Node> _active_nodes[MAX_ACTIVE_NODES]; WeakPtr<Raul::MIDISink> _sink; bool _is_activated; @@ -76,7 +80,6 @@ private: Raul::BeatTime _time; Nodes _nodes; - //Raul::List<SharedPtr<LearnRequest> > _pending_learns; SharedPtr<LearnRequest> _pending_learn; }; |