aboutsummaryrefslogtreecommitdiffstats
path: root/src/engine/machina
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/machina')
-rw-r--r--src/engine/machina/Atom.hpp217
-rw-r--r--src/engine/machina/Context.hpp51
-rw-r--r--src/engine/machina/Controller.hpp80
-rw-r--r--src/engine/machina/Driver.hpp86
-rw-r--r--src/engine/machina/Engine.hpp68
-rw-r--r--src/engine/machina/Evolver.hpp72
-rw-r--r--src/engine/machina/Loader.hpp49
-rw-r--r--src/engine/machina/Machine.hpp132
-rw-r--r--src/engine/machina/Model.hpp44
-rw-r--r--src/engine/machina/Mutation.hpp60
-rw-r--r--src/engine/machina/URIs.hpp93
-rw-r--r--src/engine/machina/Updates.hpp46
-rw-r--r--src/engine/machina/types.hpp69
13 files changed, 1067 insertions, 0 deletions
diff --git a/src/engine/machina/Atom.hpp b/src/engine/machina/Atom.hpp
new file mode 100644
index 0000000..710cc26
--- /dev/null
+++ b/src/engine/machina/Atom.hpp
@@ -0,0 +1,217 @@
+/*
+ This file is part of Machina.
+ Copyright 2007-2013 David Robillard <http://drobilla.net>
+
+ Raul 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 3 of the License, or any later version.
+
+ Raul 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 Raul. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MACHINA_ATOM_HPP
+#define MACHINA_ATOM_HPP
+
+#include <stdint.h>
+
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+
+namespace machina {
+
+class Forge;
+
+/**
+ A generic typed data container.
+
+ An Atom holds a value with some type and size, both specified by a uint32_t.
+ Values with size less than sizeof(void*) are stored inline: no dynamic
+ allocation occurs so Atoms may be created in hard real-time threads.
+ Otherwise, if the size is larger than sizeof(void*), the value will be
+ dynamically allocated in a separate chunk of memory.
+*/
+class Atom {
+public:
+ Atom() : _size(0), _type(0) { _val._blob = NULL; }
+ ~Atom() { dealloc(); }
+
+ typedef uint32_t TypeID;
+
+ /** Contruct a raw atom.
+ *
+ * Typically this is not used directly, use Forge methods to make atoms.
+ */
+ Atom(uint32_t size, TypeID type, const void* body)
+ : _size(size)
+ , _type(type)
+ {
+ if (is_reference()) {
+ _val._blob = malloc(size);
+ }
+ if (body) {
+ memcpy(get_body(), body, size);
+ }
+ }
+
+ Atom(const Atom& copy)
+ : _size(copy._size)
+ , _type(copy._type)
+ {
+ if (is_reference()) {
+ _val._blob = malloc(_size);
+ memcpy(_val._blob, copy._val._blob, _size);
+ } else {
+ memcpy(&_val, &copy._val, _size);
+ }
+ }
+
+ Atom& operator=(const Atom& other) {
+ if (&other == this) {
+ return *this;
+ }
+ dealloc();
+ _size = other._size;
+ _type = other._type;
+ if (is_reference()) {
+ _val._blob = malloc(_size);
+ memcpy(_val._blob, other._val._blob, _size);
+ } else {
+ memcpy(&_val, &other._val, _size);
+ }
+ return *this;
+ }
+
+ inline bool operator==(const Atom& other) const {
+ if (_type == other.type() && _size == other.size()) {
+ if (is_reference()) {
+ return !memcmp(_val._blob, other._val._blob, _size);
+ } else {
+ return !memcmp(&_val, &other._val, _size);
+ }
+ }
+ return false;
+ }
+
+ inline bool operator!=(const Atom& other) const {
+ return !operator==(other);
+ }
+
+ inline bool operator<(const Atom& other) const {
+ if (_type == other.type()) {
+ if (is_reference()) {
+ return memcmp(_val._blob, other._val._blob, _size) < 0;
+ } else {
+ return memcmp(&_val, &other._val, _size) < 0;
+ }
+ }
+ return _type < other.type();
+ }
+
+ inline uint32_t size() const { return _size; }
+ inline bool is_valid() const { return _type; }
+ inline TypeID type() const { return _type; }
+
+ inline const void* get_body() const {
+ return is_reference() ? _val._blob : &_val;
+ }
+
+ inline void* get_body() {
+ return is_reference() ? _val._blob : &_val;
+ }
+
+ template <typename T> const T& get() const {
+ assert(size() == sizeof(T));
+ return *static_cast<const T*>(get_body());
+ }
+
+ template <typename T> const T* ptr() const {
+ return static_cast<const T*>(get_body());
+ }
+
+private:
+ friend class Forge;
+
+ /** Free dynamically allocated value, if applicable. */
+ inline void dealloc() {
+ if (is_reference()) {
+ free(_val._blob);
+ }
+ }
+
+ /** Return true iff this value is dynamically allocated. */
+ inline bool is_reference() const {
+ return _size > sizeof(_val);
+ }
+
+ uint32_t _size;
+ TypeID _type;
+
+ union {
+ intptr_t _val;
+ void* _blob;
+ } _val;
+};
+
+class Forge {
+public:
+ Forge()
+ : Int(1)
+ , Float(2)
+ , Bool(3)
+ , URI(4)
+ , URID(5)
+ , String(6)
+ {}
+
+ virtual ~Forge() {}
+
+ Atom make() { return Atom(); }
+ Atom make(int32_t v) { return Atom(sizeof(v), Int, &v); }
+ Atom make(float v) { return Atom(sizeof(v), Float, &v); }
+ Atom make(bool v) {
+ const int32_t iv = v ? 1 : 0;
+ return Atom(sizeof(int32_t), Bool, &iv);
+ }
+
+ Atom make_urid(int32_t v) { return Atom(sizeof(int32_t), URID, &v); }
+
+ Atom alloc(uint32_t size, uint32_t type, const void* val) {
+ return Atom(size, type, val);
+ }
+
+ Atom alloc(const char* v) {
+ const size_t len = strlen(v);
+ return Atom(len + 1, String, v);
+ }
+
+ Atom alloc(const std::string& v) {
+ return Atom(v.length() + 1, String, v.c_str());
+ }
+
+ Atom alloc_uri(const char* v) {
+ const size_t len = strlen(v);
+ return Atom(len + 1, URI, v);
+ }
+
+ Atom alloc_uri(const std::string& v) {
+ return Atom(v.length() + 1, URI, v.c_str());
+ }
+
+ Atom::TypeID Int;
+ Atom::TypeID Float;
+ Atom::TypeID Bool;
+ Atom::TypeID URI;
+ Atom::TypeID URID;
+ Atom::TypeID String;
+};
+
+} // namespace machina
+
+#endif // MACHINA_ATOM_HPP
diff --git a/src/engine/machina/Context.hpp b/src/engine/machina/Context.hpp
new file mode 100644
index 0000000..766975b
--- /dev/null
+++ b/src/engine/machina/Context.hpp
@@ -0,0 +1,51 @@
+/*
+ This file is part of Machina.
+ Copyright 2007-2013 David Robillard <http://drobilla.net>
+
+ Machina 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 3 of the License, or any later version.
+
+ Machina 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 Machina. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MACHINA_CONTEXT_HPP
+#define MACHINA_CONTEXT_HPP
+
+#include "machina/Atom.hpp"
+#include "machina/types.hpp"
+#include "raul/TimeSlice.hpp"
+
+namespace machina {
+
+class MIDISink;
+
+class Context
+{
+public:
+ Context(Forge& forge, uint32_t rate, uint32_t ppqn, double bpm)
+ : _forge(forge)
+ , _time(rate, ppqn, bpm)
+ {}
+
+ void set_sink(MIDISink* sink) { _sink = sink; }
+
+ Forge& forge() { return _forge; }
+ const Raul::TimeSlice& time() const { return _time; }
+ Raul::TimeSlice& time() { return _time; }
+ MIDISink* sink() { return _sink; }
+
+private:
+ Forge& _forge;
+ Raul::TimeSlice _time;
+ MIDISink* _sink;
+};
+
+} // namespace machina
+
+#endif // MACHINA_CONTEXT_HPP
diff --git a/src/engine/machina/Controller.hpp b/src/engine/machina/Controller.hpp
new file mode 100644
index 0000000..833b5b2
--- /dev/null
+++ b/src/engine/machina/Controller.hpp
@@ -0,0 +1,80 @@
+/*
+ This file is part of Machina.
+ Copyright 2007-2014 David Robillard <http://drobilla.net>
+
+ Machina 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 3 of the License, or any later version.
+
+ Machina 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 Machina. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MACHINA_CONTROLLER_HPP
+#define MACHINA_CONTROLLER_HPP
+
+#include <stdint.h>
+
+#include <set>
+
+#include "raul/RingBuffer.hpp"
+#include "raul/Maid.hpp"
+
+#include "machina/Model.hpp"
+#include "machina/URIs.hpp"
+#include "machina/types.hpp"
+
+#include "Stateful.hpp"
+
+namespace Raul {
+class Atom;
+}
+
+namespace machina {
+
+class Engine;
+class Machine;
+
+class Controller
+{
+public:
+ Controller(SPtr<Engine> engine, Model& model);
+
+ uint64_t create(const Properties& properties);
+ uint64_t connect(uint64_t tail_id, uint64_t head_id);
+
+ void set_property(uint64_t object_id, URIInt key, const Atom& value);
+
+ void learn(SPtr<Raul::Maid> maid, uint64_t node_id);
+ void disconnect(uint64_t tail_id, uint64_t head_id);
+ void erase(uint64_t id);
+
+ void announce(SPtr<Machine> machine);
+
+ void process_updates();
+
+private:
+ SPtr<Stateful> find(uint64_t id);
+
+ struct StatefulComparator {
+ inline bool operator()(SPtr<Stateful> a, SPtr<Stateful> b) const {
+ return a->id() < b->id();
+ }
+ };
+
+ typedef std::set<SPtr<Stateful>, StatefulComparator> Objects;
+ Objects _objects;
+
+ SPtr<Engine> _engine;
+ Model& _model;
+
+ SPtr<Raul::RingBuffer> _updates;
+};
+
+}
+
+#endif // MACHINA_CONTROLLER_HPP
diff --git a/src/engine/machina/Driver.hpp b/src/engine/machina/Driver.hpp
new file mode 100644
index 0000000..546c4d6
--- /dev/null
+++ b/src/engine/machina/Driver.hpp
@@ -0,0 +1,86 @@
+/*
+ This file is part of Machina.
+ Copyright 2007-2013 David Robillard <http://drobilla.net>
+
+ Machina 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 3 of the License, or any later version.
+
+ Machina 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 Machina. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MACHINA_DRIVER_HPP
+#define MACHINA_DRIVER_HPP
+
+#include "raul/RingBuffer.hpp"
+
+#include "machina/types.hpp"
+
+#include "MIDISink.hpp"
+
+namespace machina {
+
+class Machine;
+
+class Driver : public MIDISink
+{
+public:
+ Driver(Forge& forge, SPtr<Machine> machine)
+ : _forge(forge)
+ , _machine(machine)
+ , _play_state(PlayState::STOPPED)
+ , _bpm(120.0)
+ , _quantization(0.125)
+ , _quantize_record(0)
+ {}
+
+ enum class PlayState {
+ STOPPED,
+ PLAYING,
+ RECORDING,
+ STEP_RECORDING
+ };
+
+ virtual ~Driver() {}
+
+ SPtr<Machine> machine() { return _machine; }
+
+ virtual void set_machine(SPtr<Machine> machine) {
+ _machine = machine;
+ }
+
+ SPtr<Raul::RingBuffer> update_sink() { return _updates; }
+
+ void set_update_sink(SPtr<Raul::RingBuffer> b) {
+ _updates = b;
+ }
+
+ virtual void set_bpm(double bpm) { _bpm = bpm; }
+ virtual void set_quantization(double q) { _quantization = q; }
+ virtual void set_quantize_record(bool q) { _quantize_record = q; }
+ virtual void set_play_state(PlayState state) { _play_state = state; }
+
+ virtual bool is_activated() const { return false; }
+ virtual void activate() {}
+ virtual void deactivate() {}
+
+ PlayState play_state() const { return _play_state; }
+
+protected:
+ Forge& _forge;
+ SPtr<Machine> _machine;
+ SPtr<Raul::RingBuffer> _updates;
+ PlayState _play_state;
+ double _bpm;
+ double _quantization;
+ bool _quantize_record;
+};
+
+} // namespace machina
+
+#endif // MACHINA_JACKDRIVER_HPP
diff --git a/src/engine/machina/Engine.hpp b/src/engine/machina/Engine.hpp
new file mode 100644
index 0000000..dd40f42
--- /dev/null
+++ b/src/engine/machina/Engine.hpp
@@ -0,0 +1,68 @@
+/*
+ This file is part of Machina.
+ Copyright 2007-2013 David Robillard <http://drobilla.net>
+
+ Machina 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 3 of the License, or any later version.
+
+ Machina 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 Machina. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MACHINA_ENGINE_HPP
+#define MACHINA_ENGINE_HPP
+
+#include <string>
+
+#include "machina/Atom.hpp"
+#include "machina/Driver.hpp"
+#include "machina/Loader.hpp"
+#include "machina/types.hpp"
+
+namespace machina {
+
+class Machine;
+
+class Engine
+{
+public:
+ Engine(Forge& forge,
+ SPtr<Driver> driver,
+ Sord::World& rdf_world);
+
+ Sord::World& rdf_world() { return _rdf_world; }
+
+ static SPtr<Driver> new_driver(Forge& forge,
+ const std::string& name,
+ SPtr<Machine> machine);
+
+ SPtr<Driver> driver() { return _driver; }
+ SPtr<Machine> machine() { return _driver->machine(); }
+ Forge& forge() { return _forge; }
+
+ SPtr<Machine> load_machine(const std::string& uri);
+ SPtr<Machine> load_machine_midi(const std::string& uri,
+ double q,
+ Raul::TimeDuration dur);
+
+ void export_midi(const std::string& filename,
+ Raul::TimeDuration dur);
+
+ void set_bpm(double bpm);
+ void set_quantization(double beat_fraction);
+
+private:
+ SPtr<Driver> _driver;
+ Sord::World& _rdf_world;
+ Loader _loader;
+ Forge _forge;
+};
+
+} // namespace machina
+
+#endif // MACHINA_ENGINE_HPP
diff --git a/src/engine/machina/Evolver.hpp b/src/engine/machina/Evolver.hpp
new file mode 100644
index 0000000..400c177
--- /dev/null
+++ b/src/engine/machina/Evolver.hpp
@@ -0,0 +1,72 @@
+/*
+ This file is part of Machina.
+ Copyright 2007-2017 David Robillard <http://drobilla.net>
+
+ Machina 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 3 of the License, or any later version.
+
+ Machina 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 Machina. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MACHINA_EVOLVER_HPP
+#define MACHINA_EVOLVER_HPP
+
+#include <atomic>
+#include <memory>
+#include <thread>
+
+#include "eugene/GA.hpp"
+#include "eugene/Random.hpp"
+#include "machina/types.hpp"
+#include "raul/TimeStamp.hpp"
+
+#include "Machine.hpp"
+#include "Schrodinbit.hpp"
+
+namespace eugene {
+template<typename G> class HybridMutation;
+}
+
+namespace machina {
+
+class Problem;
+
+class Evolver
+{
+public:
+ Evolver(Raul::TimeUnit unit,
+ const std::string& target_midi,
+ SPtr<Machine> seed);
+
+ void seed(SPtr<Machine> parent);
+ bool improvement() { return _improvement; }
+
+ void start();
+ void join();
+
+ const Machine& best() { return _ga->best(); }
+
+ typedef eugene::GA<Machine> MachinaGA;
+
+private:
+ void run();
+
+ eugene::Random _rng;
+ SPtr<MachinaGA> _ga;
+ SPtr<Problem> _problem;
+ float _seed_fitness;
+ Schrodinbit _improvement;
+ std::atomic<bool> _exit_flag;
+
+ std::unique_ptr<std::thread> _thread;
+};
+
+} // namespace machina
+
+#endif // MACHINA_EVOLVER_HPP
diff --git a/src/engine/machina/Loader.hpp b/src/engine/machina/Loader.hpp
new file mode 100644
index 0000000..3fa66ff
--- /dev/null
+++ b/src/engine/machina/Loader.hpp
@@ -0,0 +1,49 @@
+/*
+ This file is part of Machina.
+ Copyright 2007-2013 David Robillard <http://drobilla.net>
+
+ Machina 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 3 of the License, or any later version.
+
+ Machina 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 Machina. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MACHINA_LOADER_HPP
+#define MACHINA_LOADER_HPP
+
+#include "machina/Atom.hpp"
+#include "machina/types.hpp"
+#include "raul/TimeStamp.hpp"
+#include "sord/sordmm.hpp"
+
+using Sord::Namespaces;
+
+namespace machina {
+
+class Machine;
+
+class Loader
+{
+public:
+ Loader(Forge& forge, Sord::World& rdf_world);
+
+ SPtr<Machine> load(const std::string& filename);
+
+ SPtr<Machine> load_midi(const std::string& filename,
+ double q,
+ Raul::TimeDuration dur);
+
+private:
+ Forge& _forge;
+ Sord::World& _rdf_world;
+};
+
+} // namespace machina
+
+#endif // MACHINA_LOADER_HPP
diff --git a/src/engine/machina/Machine.hpp b/src/engine/machina/Machine.hpp
new file mode 100644
index 0000000..7c9855d
--- /dev/null
+++ b/src/engine/machina/Machine.hpp
@@ -0,0 +1,132 @@
+/*
+ This file is part of Machina.
+ Copyright 2007-2013 David Robillard <http://drobilla.net>
+
+ Machina 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 3 of the License, or any later version.
+
+ Machina 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 Machina. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MACHINA_MACHINE_HPP
+#define MACHINA_MACHINE_HPP
+
+#include <vector>
+#include <set>
+
+#include "machina/types.hpp"
+#include "machina/Atom.hpp"
+#include "raul/RingBuffer.hpp"
+#include "raul/TimeSlice.hpp"
+#include "sord/sordmm.hpp"
+
+#include "types.hpp"
+#include "Node.hpp"
+
+namespace machina {
+
+class Context;
+class LearnRequest;
+
+/** A (Finite State) Machine.
+ */
+class Machine : public Stateful
+{
+public:
+ explicit Machine(TimeUnit unit);
+
+ /** Copy a Machine.
+ *
+ * Creates a deep copy which is the 'same' machine, but with fresh state,
+ * i.e. all nodes are inactive and time is at zero.
+ */
+ Machine(const Machine& copy);
+
+ /** Completely replace this machine's contents with a deep copy. */
+ Machine& operator=(const Machine& copy);
+
+ bool operator==(const Machine& rhs) const;
+
+ /** Merge another machine into this machine. */
+ void merge(const Machine& machine);
+
+ bool is_empty() { return _nodes.empty(); }
+ bool is_finished() { return _is_finished; }
+
+ void add_node(SPtr<Node> node);
+ void remove_node(SPtr<Node> node);
+ void learn(SPtr<Raul::Maid> maid, SPtr<Node> node);
+
+ void write_state(Sord::Model& model);
+
+ /** Exit all active nodes and reset time to 0. */
+ void reset(MIDISink* sink, Raul::TimeStamp time);
+
+ /** Run the machine for a (real) time slice.
+ *
+ * Returns the duration of time the machine actually ran in frames.
+ *
+ * Caller can check is_finished() to determine if the machine still has any
+ * active nodes. If not, time() will return the exact time stamp the
+ * machine actually finished on (so it can be restarted immediately
+ * with sample accuracy if necessary).
+ */
+ uint32_t run(Context& context, SPtr<Raul::RingBuffer> updates);
+
+ // Any context
+ inline Raul::TimeStamp time() const { return _time; }
+
+ SPtr<LearnRequest> pending_learn() { return _pending_learn; }
+ void clear_pending_learn() { _pending_learn.reset(); }
+
+ typedef std::set< SPtr<Node> > Nodes;
+ Nodes& nodes() { return _nodes; }
+ const Nodes& nodes() const { return _nodes; }
+
+ SPtr<Node> initial_node() const { return _initial_node; }
+
+ SPtr<Node> random_node();
+ SPtr<Edge> random_edge();
+
+ float fitness; // For GA
+
+private:
+ /** Return the active Node with the earliest exit time. */
+ SPtr<Node> earliest_node() const;
+
+ void assign(const Machine& other);
+
+ /** Enter a node at the current time (called by run()).
+ *
+ * @return true if node was entered, otherwise voics are exhausted.
+ */
+ bool enter_node(Context& context,
+ SPtr<Node> node,
+ SPtr<Raul::RingBuffer> updates);
+
+ /** Exit a node at the current time (called by run()). */
+ void exit_node(Context& context,
+ SPtr<Node> node,
+ SPtr<Raul::RingBuffer> updates);
+
+ static const size_t MAX_ACTIVE_NODES = 128;
+
+ SPtr<Node> _initial_node;
+ std::vector< SPtr<Node> > _active_nodes;
+
+ SPtr<LearnRequest> _pending_learn;
+ Nodes _nodes;
+ Raul::TimeStamp _time;
+
+ bool _is_finished;
+};
+
+} // namespace machina
+
+#endif // MACHINA_MACHINE_HPP
diff --git a/src/engine/machina/Model.hpp b/src/engine/machina/Model.hpp
new file mode 100644
index 0000000..32a332e
--- /dev/null
+++ b/src/engine/machina/Model.hpp
@@ -0,0 +1,44 @@
+/*
+ This file is part of Machina.
+ Copyright 2014 David Robillard <http://drobilla.net>
+
+ Machina 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 3 of the License, or any later version.
+
+ Machina 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 Machina. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MACHINA_MODEL_HPP
+#define MACHINA_MODEL_HPP
+
+#include <stdint.h>
+
+#include <map>
+
+#include "machina/Atom.hpp"
+#include "machina/types.hpp"
+
+namespace machina {
+
+class Model
+{
+public:
+ virtual ~Model() {}
+
+ virtual void new_object(uint64_t id, const Properties& properties) = 0;
+
+ virtual void erase_object(uint64_t id) = 0;
+
+ virtual void set(uint64_t id, URIInt key, const Atom& value) = 0;
+ virtual const Atom& get(uint64_t id, URIInt key) const = 0;
+};
+
+} // namespace machina
+
+#endif // MACHINA_MODEL_HPP
diff --git a/src/engine/machina/Mutation.hpp b/src/engine/machina/Mutation.hpp
new file mode 100644
index 0000000..69f5ee4
--- /dev/null
+++ b/src/engine/machina/Mutation.hpp
@@ -0,0 +1,60 @@
+/*
+ This file is part of Machina.
+ Copyright 2007-2013 David Robillard <http://drobilla.net>
+
+ Machina 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 3 of the License, or any later version.
+
+ Machina 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 Machina. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MACHINA_MACHINE_MUTATION_HPP
+#define MACHINA_MACHINE_MUTATION_HPP
+
+#include "machina_config.h"
+
+#ifdef HAVE_EUGENE
+# include "eugene/Mutation.hpp"
+# define SUPER : public eugene::Mutation<Machine>
+#else
+# define SUPER : public Mutation
+#endif
+
+namespace machina {
+
+#ifdef HAVE_EUGENE
+typedef eugene::Random Random;
+#else
+struct Random {};
+#endif
+
+class Machine;
+
+namespace Mutation {
+
+struct Mutation {
+ virtual ~Mutation() {}
+
+ virtual void mutate(Random& rng, Machine& machine) = 0;
+};
+
+struct Compress SUPER { void mutate(Random& rng, Machine& machine); };
+struct AddNode SUPER { void mutate(Random& rng, Machine& machine); };
+struct RemoveNode SUPER { void mutate(Random& rng, Machine& machine); };
+struct AdjustNode SUPER { void mutate(Random& rng, Machine& machine); };
+struct SwapNodes SUPER { void mutate(Random& rng, Machine& machine); };
+struct AddEdge SUPER { void mutate(Random& rng, Machine& machine); };
+struct RemoveEdge SUPER { void mutate(Random& rng, Machine& machine); };
+struct AdjustEdge SUPER { void mutate(Random& rng, Machine& machine); };
+
+} // namespace Mutation
+
+} // namespace machina
+
+#endif // MACHINA_MACHINE_MUTATION_HPP
diff --git a/src/engine/machina/URIs.hpp b/src/engine/machina/URIs.hpp
new file mode 100644
index 0000000..f770723
--- /dev/null
+++ b/src/engine/machina/URIs.hpp
@@ -0,0 +1,93 @@
+/*
+ This file is part of Machina.
+ Copyright 2007-2013 David Robillard <http://drobilla.net>
+
+ Machina 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 3 of the License, or any later version.
+
+ Machina 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 Machina. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MACHINA_URIS_HPP
+#define MACHINA_URIS_HPP
+
+#include <stdint.h>
+
+#include "machina/Atom.hpp"
+#include "machina/types.hpp"
+
+#define MACHINA_URI_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+
+#define MACHINA_NS "http://drobilla.net/ns/machina#"
+
+#define MACHINA_NS_Machine MACHINA_NS "Machine"
+#define MACHINA_NS_Node MACHINA_NS "Node"
+#define MACHINA_NS_SelectorNode MACHINA_NS "SelectorNode"
+#define MACHINA_NS_arc MACHINA_NS "arc"
+#define MACHINA_NS_duration MACHINA_NS "duration"
+#define MACHINA_NS_head MACHINA_NS "head"
+#define MACHINA_NS_node MACHINA_NS "node"
+#define MACHINA_NS_onEnter MACHINA_NS "onEnter"
+#define MACHINA_NS_onExit MACHINA_NS "onExit"
+#define MACHINA_NS_probability MACHINA_NS "probability"
+#define MACHINA_NS_start MACHINA_NS "start"
+#define MACHINA_NS_tail MACHINA_NS "tail"
+
+namespace machina {
+
+class URIs
+{
+public:
+ static void init() { _instance = new URIs(); }
+
+ static inline const URIs& instance() { assert(_instance); return *_instance; }
+
+ URIInt machina_Edge;
+ URIInt machina_MidiAction;
+ URIInt machina_Node;
+ URIInt machina_active;
+ URIInt machina_canvas_x;
+ URIInt machina_canvas_y;
+ URIInt machina_duration;
+ URIInt machina_enter_action;
+ URIInt machina_exit_action;
+ URIInt machina_head_id;
+ URIInt machina_initial;
+ URIInt machina_note_number;
+ URIInt machina_probability;
+ URIInt machina_selector;
+ URIInt machina_tail_id;
+ URIInt rdf_type;
+
+private:
+ URIs()
+ : machina_Edge(100)
+ , machina_MidiAction(101)
+ , machina_Node(102)
+ , machina_active(1)
+ , machina_canvas_x(2)
+ , machina_canvas_y(3)
+ , machina_duration(4)
+ , machina_enter_action(11)
+ , machina_exit_action(12)
+ , machina_head_id(5)
+ , machina_initial(6)
+ , machina_note_number(13)
+ , machina_probability(7)
+ , machina_selector(8)
+ , machina_tail_id(9)
+ , rdf_type(10)
+ {}
+
+ static URIs* _instance;
+};
+
+} // namespace machina
+
+#endif // MACHINA_URIS_HPP
diff --git a/src/engine/machina/Updates.hpp b/src/engine/machina/Updates.hpp
new file mode 100644
index 0000000..ff09af9
--- /dev/null
+++ b/src/engine/machina/Updates.hpp
@@ -0,0 +1,46 @@
+/*
+ This file is part of Machina.
+ Copyright 2007-2013 David Robillard <http://drobilla.net>
+
+ Machina 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 3 of the License, or any later version.
+
+ Machina 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 Machina. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MACHINA_UPDATES_HPP
+#define MACHINA_UPDATES_HPP
+
+#include <stdint.h>
+
+#include "machina/Atom.hpp"
+#include "machina/types.hpp"
+#include "raul/RingBuffer.hpp"
+
+namespace machina {
+
+enum UpdateType {
+ UPDATE_SET = 1
+};
+
+void
+write_set(SPtr<Raul::RingBuffer> buf,
+ uint64_t subject,
+ URIInt key,
+ const Atom& value);
+
+uint32_t
+read_set(SPtr<Raul::RingBuffer> buf,
+ uint64_t* subject,
+ URIInt* key,
+ Atom* value);
+
+} // namespace machina
+
+#endif // MACHINA_UPDATES_HPP
diff --git a/src/engine/machina/types.hpp b/src/engine/machina/types.hpp
new file mode 100644
index 0000000..61137b7
--- /dev/null
+++ b/src/engine/machina/types.hpp
@@ -0,0 +1,69 @@
+/*
+ This file is part of Machina.
+ Copyright 2007-2014 David Robillard <http://drobilla.net>
+
+ Machina 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 3 of the License, or any later version.
+
+ Machina 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 Machina. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MACHINA_TYPES_HPP
+#define MACHINA_TYPES_HPP
+
+#include <map>
+#include <memory>
+
+#include "raul/Maid.hpp"
+
+namespace machina {
+
+typedef unsigned char byte;
+
+typedef uint32_t URIInt;
+
+class Atom;
+typedef std::map<URIInt, Atom> Properties;
+
+#if __cplusplus >= 201103L
+template <class T>
+using SPtr = std::shared_ptr<T>;
+
+template <class T>
+using WPtr = std::weak_ptr<T>;
+
+template <class T>
+using MPtr = Raul::managed_ptr<T>;
+#else
+#define SPtr std::shared_ptr
+#define WPtr std::weak_ptr
+#define MPtr Raul::managed_ptr
+#endif
+
+template <class T>
+void NullDeleter(T* ptr) {}
+
+template<class T, class U>
+SPtr<T> static_ptr_cast(const SPtr<U>& r) {
+ return std::static_pointer_cast<T>(r);
+}
+
+template<class T, class U>
+SPtr<T> dynamic_ptr_cast(const SPtr<U>& r) {
+ return std::dynamic_pointer_cast<T>(r);
+}
+
+template<class T, class U>
+SPtr<T> const_ptr_cast(const SPtr<U>& r) {
+ return std::const_pointer_cast<T>(r);
+}
+
+} // namespace machina
+
+#endif // MACHINA_TYPES_HPP