aboutsummaryrefslogtreecommitdiffstats
path: root/src/engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/JackActions.cpp88
-rw-r--r--src/engine/JackDriver.cpp102
-rw-r--r--src/engine/JackNodeFactory.cpp42
-rw-r--r--src/engine/Loader.cpp221
-rw-r--r--src/engine/Machine.cpp224
-rw-r--r--src/engine/Makefile.am17
-rw-r--r--src/engine/Node.cpp104
-rw-r--r--src/engine/machina/Action.hpp48
-rw-r--r--src/engine/machina/Driver.hpp42
-rw-r--r--src/engine/machina/Edge.hpp51
-rw-r--r--src/engine/machina/JackActions.hpp57
-rw-r--r--src/engine/machina/JackDriver.hpp60
-rw-r--r--src/engine/machina/JackNodeFactory.hpp43
-rw-r--r--src/engine/machina/Loader.hpp49
-rw-r--r--src/engine/machina/Machina.hpp28
-rw-r--r--src/engine/machina/Machine.hpp64
-rw-r--r--src/engine/machina/Makefile.am12
-rw-r--r--src/engine/machina/Node.hpp82
-rw-r--r--src/engine/machina/NodeFactory.hpp40
-rw-r--r--src/engine/machina/types.hpp31
20 files changed, 1405 insertions, 0 deletions
diff --git a/src/engine/JackActions.cpp b/src/engine/JackActions.cpp
new file mode 100644
index 0000000..b55e493
--- /dev/null
+++ b/src/engine/JackActions.cpp
@@ -0,0 +1,88 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 <iostream>
+#include "machina/JackActions.hpp"
+#include "machina/JackDriver.hpp"
+
+namespace Machina {
+
+
+/* NOTE ON */
+
+JackNoteOnAction::JackNoteOnAction(WeakPtr<JackDriver> driver,
+ unsigned char note_num)
+ : _driver(driver)
+ , _note_num(note_num)
+{
+}
+
+
+void
+JackNoteOnAction::execute(Timestamp time)
+{
+ SharedPtr<JackDriver> driver = _driver.lock();
+ if (!driver)
+ return;
+
+ const FrameCount nframes = driver->current_cycle_nframes();
+ const FrameCount offset = driver->stamp_to_offset(time);
+
+ //std::cerr << offset << " \tNOTE ON:\t" << (int)_note_num << "\t@ " << time << std::endl;
+
+ jack_midi_data_t ev[] = { 0x80, _note_num, 0x40 };
+
+ jack_midi_event_write(
+ jack_port_get_buffer(driver->output_port(), nframes),
+ offset, ev, 3, nframes);
+}
+
+
+
+/* NOTE OFF */
+
+JackNoteOffAction::JackNoteOffAction(WeakPtr<JackDriver> driver,
+ unsigned char note_num)
+ : _driver(driver)
+ , _note_num(note_num)
+{
+}
+
+
+void
+JackNoteOffAction::execute(Timestamp time)
+{
+ SharedPtr<JackDriver> driver = _driver.lock();
+ if (!driver)
+ return;
+
+ const FrameCount nframes = driver->current_cycle_nframes();
+ const FrameCount offset = driver->stamp_to_offset(time);
+
+ //std::cerr << offset << " \tNOTE OFF:\t" << (int)_note_num << "\t@ " << time << std::endl;
+
+ jack_midi_data_t ev[] = { 0x90, _note_num, 0x40 };
+
+ jack_midi_event_write(
+ jack_port_get_buffer(driver->output_port(), nframes),
+ offset, ev, 3, nframes);
+}
+
+
+} // namespace Machina
+
+
diff --git a/src/engine/JackDriver.cpp b/src/engine/JackDriver.cpp
new file mode 100644
index 0000000..848c3d7
--- /dev/null
+++ b/src/engine/JackDriver.cpp
@@ -0,0 +1,102 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 "machina/JackDriver.hpp"
+
+#include <iostream>
+
+namespace Machina {
+
+
+JackDriver::JackDriver()
+ : _output_port(NULL)
+ , _current_cycle_start(0)
+ , _current_cycle_nframes(0)
+{
+}
+
+
+void
+JackDriver::attach(const std::string& client_name)
+{
+ Raul::JackDriver::attach(client_name);
+
+ if (jack_client()) {
+ _output_port = jack_port_register(jack_client(),
+ "out",
+ JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput,
+ 0);
+ }
+}
+
+
+void
+JackDriver::detach()
+{
+ jack_port_unregister(jack_client(), _output_port);
+ _output_port = NULL;
+
+ Raul::JackDriver::detach();
+}
+
+
+Timestamp
+JackDriver::stamp_to_offset(Timestamp stamp)
+{
+ Timestamp ret = stamp - _current_cycle_start + _current_cycle_offset;
+ assert(ret < _current_cycle_offset + _current_cycle_nframes);
+ return ret;
+}
+
+
+void
+JackDriver::on_process(jack_nframes_t nframes)
+{
+ //std::cerr << "======================================================\n";
+
+ _current_cycle_offset = 0;
+ _current_cycle_nframes = nframes;
+
+ jack_midi_clear_buffer(jack_port_get_buffer(_output_port, nframes), nframes);
+
+ while (true) {
+
+ bool machine_done = ! _machine->run(_current_cycle_nframes);
+
+ if (!machine_done) {
+ _current_cycle_start += _current_cycle_nframes;
+ break;
+
+ } else {
+ const Timestamp finish_time = _machine->time();
+ const FrameCount finish_offset = stamp_to_offset(finish_time);
+
+ if (finish_offset >= _current_cycle_nframes)
+ break;
+
+ _current_cycle_offset = stamp_to_offset(finish_time);
+ _current_cycle_nframes -= _current_cycle_offset;
+ _current_cycle_start = 0;
+ _machine->reset();
+ }
+ }
+
+ //std::cerr << "======================================================\n";
+}
+
+
+} // namespace Machina
diff --git a/src/engine/JackNodeFactory.cpp b/src/engine/JackNodeFactory.cpp
new file mode 100644
index 0000000..09670e1
--- /dev/null
+++ b/src/engine/JackNodeFactory.cpp
@@ -0,0 +1,42 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 "machina/JackNodeFactory.hpp"
+#include "machina/JackActions.hpp"
+#include "machina/Node.hpp"
+
+namespace Machina {
+
+
+SharedPtr<Node>
+JackNodeFactory::create_node(Node::ID, unsigned char note, FrameCount duration)
+{
+ // FIXME: leaks like a sieve, obviously
+
+ Node* n = new Node(duration);
+ JackNoteOnAction* a_enter = new JackNoteOnAction(_driver, note);
+ JackNoteOffAction* a_exit = new JackNoteOffAction(_driver, note);
+
+ n->add_enter_action(a_enter);
+ n->add_exit_action(a_exit);
+
+ return SharedPtr<Node>(n);
+}
+
+
+} // namespace Machina
+
diff --git a/src/engine/Loader.cpp b/src/engine/Loader.cpp
new file mode 100644
index 0000000..3b58537
--- /dev/null
+++ b/src/engine/Loader.cpp
@@ -0,0 +1,221 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 <iostream>
+#include <map>
+#include <raptor.h>
+#include <rasqal.h>
+#include <glibmm/ustring.h>
+#include <raul/RDFQuery.h>
+#include "machina/Loader.hpp"
+#include "machina/Node.hpp"
+#include "machina/Edge.hpp"
+#include "machina/Machine.hpp"
+#include "machina/NodeFactory.hpp"
+
+using namespace Raul;
+using std::cerr; using std::cout; using std::endl;
+
+namespace Machina {
+
+
+/*
+// FIXME: remove
+Node* create_debug_node(const Node::ID& id, FrameCount duration)
+{
+ // leaks like a sieve, obviously
+
+ Node* n = new Node(duration);
+ PrintAction* a_enter = new PrintAction(string("\t> ") + id);
+ PrintAction* a_exit = new PrintAction(string("\t< ") + id);
+
+ n->add_enter_action(a_enter);
+ n->add_exit_action(a_exit);
+
+ cerr << "dur: " << duration << endl;
+
+ return n;
+}
+*/
+
+Loader::Loader(SharedPtr<NodeFactory> node_factory,
+ SharedPtr<Namespaces> namespaces)
+ : _node_factory(node_factory)
+ , _namespaces(namespaces)
+{
+ if (!_namespaces)
+ _namespaces = SharedPtr<Namespaces>(new Namespaces());
+
+ (*_namespaces)[""] = "http://drobilla.net/ns/machina#";
+ (*_namespaces)["xsd"] = "http://www.w3.org/2001/XMLSchema#";
+}
+
+
+/** Load (create) all objects from an RDF into the engine.
+ *
+ * @param filename Filename to load objects from.
+ * @param parent Path of parent under which to load objects.
+ * @return whether or not load was successful.
+ */
+SharedPtr<Machine>
+Loader::load(const Glib::ustring& filename)
+{
+ using Raul::RDFQuery;
+ SharedPtr<Machine> machine;
+
+ rasqal_init();
+
+ unsigned char* document_uri_str = raptor_uri_filename_to_uri_string(filename.c_str());
+ assert(document_uri_str);
+ raptor_uri* document_raptor_uri = raptor_new_uri(document_uri_str);
+
+ if (!document_uri_str)
+ return machine;
+
+ machine = SharedPtr<Machine>(new Machine());
+
+ Glib::ustring document_uri = (const char*)document_uri_str;
+
+ string machine_uri = "<> ";
+
+ cout << "[Loader] Loading " << machine_uri << " from " << document_uri << endl;
+
+ typedef std::map<string, SharedPtr<Node> > Created;
+ Created created;
+
+
+ /* Get initial nodes */
+
+ Raul::RDFQuery query = Raul::RDFQuery(*_namespaces, Glib::ustring(
+ "SELECT DISTINCT ?initialNode ?midiNote ?duration FROM <")
+ + document_uri + "> WHERE {\n" +
+ machine_uri + " :initialNode ?initialNode .\n"
+ "?initialNode :midiNote ?midiNote ;\n"
+ " :duration ?duration .\n"
+ "}\n");
+
+ RDFQuery::Results results = query.run(document_uri);
+
+ for (RDFQuery::Results::iterator i = results.begin(); i != results.end(); ++i) {
+ const Glib::ustring& node_uri = (*i)["initialNode"];
+ const Glib::ustring& midi_note = (*i)["midiNote"];
+ const Glib::ustring& duration = (*i)["duration"];
+
+ raptor_uri* node_raptor_uri
+ = raptor_new_uri((const unsigned char*)node_uri.c_str());
+
+ char* node_name = (char*)
+ raptor_uri_to_relative_uri_string(document_raptor_uri, node_raptor_uri);
+
+ //cout << "Initial: " << node_name << ": " << midi_note << " - " << duration << endl;
+
+ SharedPtr<Node> node = SharedPtr<Node>(_node_factory->create_node(
+ node_name,
+ strtol(midi_note.c_str(), NULL, 10),
+ strtol(duration.c_str(), NULL, 10)));
+
+ node->set_initial(true);
+ //machine->add_node(string(node_name).substr(1), node); // (chop leading "#")
+ machine->add_node(node);
+
+ created.insert(std::make_pair(node_uri.collate_key(), node));
+
+ raptor_free_uri(node_raptor_uri);
+ free(node_name);
+ }
+
+
+ /* Get remaining nodes */
+
+ query = Raul::RDFQuery(*_namespaces, Glib::ustring(
+ "SELECT DISTINCT ?node ?midiNote ?duration FROM <")
+ + document_uri + "> WHERE {\n" +
+ machine_uri + " :node ?node .\n"
+ "?node :midiNote ?midiNote ;\n"
+ " :duration ?duration .\n"
+ "}\n");
+
+ results = query.run(document_uri);
+
+ for (RDFQuery::Results::iterator i = results.begin(); i != results.end(); ++i) {
+ const Glib::ustring& node_uri = (*i)["node"];
+ const Glib::ustring& midi_note = (*i)["midiNote"];
+ const Glib::ustring& duration = (*i)["duration"];
+
+ raptor_uri* node_raptor_uri
+ = raptor_new_uri((const unsigned char*)node_uri.c_str());
+
+ char* node_name = (char*)
+ raptor_uri_to_relative_uri_string(document_raptor_uri, node_raptor_uri);
+
+
+ SharedPtr<Node> node = SharedPtr<Node>(_node_factory->create_node(
+ node_name,
+ strtol(midi_note.c_str(), NULL, 10),
+ strtol(duration.c_str(), NULL, 10)));
+
+ if (created.find(node_uri) == created.end()) {
+ //cout << "Node: " << node_name << ": " << midi_note << " - " << duration << endl;
+ //machine->add_node(string(node_name).substr(1), node); // (chop leading "#")
+ machine->add_node(node);
+ created.insert(std::make_pair(node_uri.collate_key(), node));
+ }
+
+ raptor_free_uri(node_raptor_uri);
+ free(node_name);
+ }
+
+
+ /* Get edges */
+
+ query = Raul::RDFQuery(*_namespaces, Glib::ustring(
+ "SELECT DISTINCT ?src ?edge ?dst FROM <")
+ + document_uri + "> WHERE {\n" +
+ machine_uri + " :edge ?edge .\n"
+ "?edge :tail ?src ;\n"
+ " :head ?dst .\n }");
+ results = query.run(document_uri);
+
+ for (RDFQuery::Results::iterator i = results.begin(); i != results.end(); ++i) {
+ const Glib::ustring& src_uri = (*i)["src"];
+ const Glib::ustring& dst_uri = (*i)["dst"];
+
+ Created::iterator src_i = created.find(src_uri.collate_key());
+ Created::iterator dst_i = created.find(dst_uri.collate_key());
+
+ if (src_i != created.end() && dst_i != created.end()) {
+ const SharedPtr<Node> src = src_i->second;
+ const SharedPtr<Node> dst = dst_i->second;
+
+ src->add_outgoing_edge(SharedPtr<Edge>(new Edge(src, dst)));
+
+ } else {
+ cerr << "[Loader] WARNING: Ignored edge between unknown nodes "
+ << src_uri << " -> " << dst_uri << endl;
+ }
+
+ }
+
+ free(document_uri_str);
+ raptor_free_uri(document_raptor_uri);
+
+ return machine;
+}
+
+
+} // namespace Machina
+
diff --git a/src/engine/Machine.cpp b/src/engine/Machine.cpp
new file mode 100644
index 0000000..426ffd3
--- /dev/null
+++ b/src/engine/Machine.cpp
@@ -0,0 +1,224 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <algorithm>
+#include "machina/Machine.hpp"
+#include "machina/Node.hpp"
+#include "machina/Edge.hpp"
+
+namespace Machina {
+
+
+Machine::Machine()
+ : _is_activated(false)
+ , _is_finished(false)
+ , _time(0)
+{
+}
+
+
+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()
+{
+ 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;
+}
+
+
+/** 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::exit_node(const SharedPtr<Node> 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);
+
+ }
+}
+
+
+/** 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)
+{
+ if (_is_finished)
+ return false;
+
+ if (_nodes.size() == 0)
+ return true;
+
+ const FrameCount cycle_end = _time + nframes;
+
+ assert(_is_activated);
+
+ //std::cerr << "--------- " << _time << " - " << _time + nframes << std::endl;
+
+ // 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;
+
+ for (std::vector<Node*>::iterator i = _voices.begin();
+ i != _voices.end(); ++i) {
+
+ Node* const n = *i;
+
+ // Active voice which ends within this cycle, transition
+ if (n && n->is_active() && n->end_time() < cycle_end) {
+ // Guaranteed to be within this cycle
+ const FrameCount end_time = std::max(_time, n->end_time());
+ n->exit(std::max(_time, n->end_time()));
+ done = false;
+
+ // Greedily grab one of the successors with the voice already
+ // on this node so voices follow paths nicely
+ for (Node::EdgeList::const_iterator s = n->outgoing_edges().begin();
+ s != n->outgoing_edges().end(); ++s) {
+ Node* dst = (*s)->dst();
+ if (!dst->is_active()) {
+ dst->enter(end_time);
+ *i = dst;
+ break;
+ }
+ }
+
+ latest_event = end_time;
+ }
+
+ }
+
+ // FIXME: use free voices to claim any 'free successors'
+ // (when nodes have multiple successors and one gets chosen in the
+ // greedy bit above)
+
+ // If every voice is on the initial node...
+ bool is_reset = true;
+ for (std::vector<Node*>::iterator i = _voices.begin();
+ i != _voices.end(); ++i)
+ if ((*i) != NULL && (*i)->is_active())
+ is_reset = false;
+
+ // ... then start
+ if (is_reset) {
+
+ std::vector<Node*>::iterator n = _voices.begin();
+ for (Node::EdgeList::const_iterator s = _initial_node->outgoing_edges().begin();
+ s != _initial_node->outgoing_edges().end() && n != _voices.end();
+ ++s, ++n) {
+ (*s)->dst()->enter(latest_event);
+ done = false;
+ *n = (*s)->dst();
+ }
+ }
+ }
+ _time += nframes;
+
+ return false;
+#endif
+}
+
+
+} // namespace Machina
+
diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am
new file mode 100644
index 0000000..2e0c363
--- /dev/null
+++ b/src/engine/Makefile.am
@@ -0,0 +1,17 @@
+SUBDIRS = machina
+
+lib_LTLIBRARIES = libmachina.la
+
+libmachina_la_CXXFLAGS = @RAUL_CFLAGS@ @JACK_CFLAGS@ @GLIBMM_CFLAGS@
+libmachina_la_LIBADD = @RAUL_LIBS@ @JACK_LIBS@ @GLIBMM_LIBS@
+
+
+libmachina_la_SOURCES = \
+ Node.cpp \
+ Machine.cpp \
+ Loader.h \
+ Loader.cpp \
+ JackDriver.h \
+ JackDriver.cpp \
+ JackActions.cpp \
+ JackNodeFactory.cpp
diff --git a/src/engine/Node.cpp b/src/engine/Node.cpp
new file mode 100644
index 0000000..def7a70
--- /dev/null
+++ b/src/engine/Node.cpp
@@ -0,0 +1,104 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <cassert>
+#include "machina/Node.hpp"
+#include "machina/Edge.hpp"
+
+namespace Machina {
+
+
+Node::Node(FrameCount duration, bool initial)
+ : _is_initial(initial)
+ , _is_active(false)
+ , _enter_time(0)
+ , _duration(duration)
+ , _enter_action(NULL)
+ , _exit_action(NULL)
+{
+}
+
+
+void
+Node::add_enter_action(Action* action)
+{
+ assert(!_enter_action);
+ _enter_action = action;
+}
+
+
+void
+Node::remove_enter_action(Action* /*action*/)
+{
+ _enter_action = NULL;
+}
+
+
+
+void
+Node::add_exit_action(Action* action)
+{
+ assert(!_exit_action);
+ _exit_action = action;
+}
+
+
+void
+Node::remove_exit_action(Action* /*action*/)
+{
+ _exit_action = NULL;
+}
+
+
+void
+Node::enter(Timestamp time)
+{
+ _is_active = true;
+ _enter_time = time;
+ if (_enter_action)
+ _enter_action->execute(time);
+}
+
+
+void
+Node::exit(Timestamp time)
+{
+ if (_exit_action)
+ _exit_action->execute(time);
+ _is_active = false;
+ _enter_time = 0;
+}
+
+
+void
+Node::add_outgoing_edge(SharedPtr<Edge> edge)
+{
+ assert(edge->src().lock().get() == this);
+
+ _outgoing_edges.push_back(edge);
+}
+
+
+void
+Node::remove_outgoing_edge(SharedPtr<Edge> edge)
+{
+ _outgoing_edges.erase(_outgoing_edges.find(edge));
+}
+
+
+} // namespace Machina
+
diff --git a/src/engine/machina/Action.hpp b/src/engine/machina/Action.hpp
new file mode 100644
index 0000000..ffee5b1
--- /dev/null
+++ b/src/engine/machina/Action.hpp
@@ -0,0 +1,48 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef MACHINA_ACTION_HPP
+#define MACHINA_ACTION_HPP
+
+#include <string>
+#include <iostream>
+#include "types.hpp"
+
+namespace Machina {
+
+
+struct Action {
+ virtual ~Action() {}
+
+ virtual void execute(Timestamp /*time*/) {}
+};
+
+
+class PrintAction : public Action {
+public:
+ PrintAction(const std::string& msg) : _msg(msg) {}
+
+ void execute(Timestamp time) { std::cout << "t=" << time << ": " << _msg << std::endl; }
+
+private:
+ std::string _msg;
+};
+
+
+} // namespace Machina
+
+#endif // MACHINA_ACTION_HPP
diff --git a/src/engine/machina/Driver.hpp b/src/engine/machina/Driver.hpp
new file mode 100644
index 0000000..f2816ba
--- /dev/null
+++ b/src/engine/machina/Driver.hpp
@@ -0,0 +1,42 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 MACHINA_JACKDRIVER_HPP
+#define MACHINA_JACKDRIVER_HPP
+
+#include <raul/JackDriver.h>
+
+namespace Machine {
+
+
+class JackDriver : public Raul::JackDriver {
+public:
+ JackDriver(SharedPtr<Machine> machine);
+
+ virtual void set_machine(SharedPtr<Machine> machine);
+
+protected:
+ virtual void on_process(jack_nframes_t nframes);
+
+private:
+ SharedPtr<Machine> _machine;
+};
+
+
+} // namespace Machina
+
+#endif // MACHINA_JACKDRIVER_HPP
diff --git a/src/engine/machina/Edge.hpp b/src/engine/machina/Edge.hpp
new file mode 100644
index 0000000..f20e5db
--- /dev/null
+++ b/src/engine/machina/Edge.hpp
@@ -0,0 +1,51 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef MACHINA_EDGE_HPP
+#define MACHINA_EDGE_HPP
+
+#include <list>
+#include <boost/utility.hpp>
+#include <raul/WeakPtr.h>
+#include <raul/SharedPtr.h>
+#include "types.hpp"
+#include "Action.hpp"
+
+namespace Machina {
+
+class Node;
+
+class Edge : boost::noncopyable {
+public:
+
+ Edge(WeakPtr<Node> src, SharedPtr<Node> dst) : _src(src) , _dst(dst) {}
+
+ WeakPtr<Node> src() { return _src; }
+ SharedPtr<Node> dst() { return _dst; }
+
+ void set_src(WeakPtr<Node> src) { _src = src; }
+ void set_dst(SharedPtr<Node> dst) { _dst = dst; }
+
+private:
+ WeakPtr<Node> _src;
+ SharedPtr<Node> _dst;
+};
+
+
+} // namespace Machina
+
+#endif // MACHINA_EDGE_HPP
diff --git a/src/engine/machina/JackActions.hpp b/src/engine/machina/JackActions.hpp
new file mode 100644
index 0000000..0eb50b8
--- /dev/null
+++ b/src/engine/machina/JackActions.hpp
@@ -0,0 +1,57 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 MACHINA_JACKACTIONS_HPP
+#define MACHINA_JACKACTIONS_HPP
+
+#include <raul/WeakPtr.h>
+#include "types.hpp"
+#include "Action.hpp"
+
+namespace Machina {
+
+class Node;
+class JackDriver;
+
+
+class JackNoteOnAction : public Action {
+public:
+ JackNoteOnAction(WeakPtr<JackDriver> driver, unsigned char note_num);
+
+ void execute(Timestamp time);
+
+private:
+ WeakPtr<JackDriver> _driver;
+ unsigned char _note_num;
+};
+
+
+class JackNoteOffAction : public Action {
+public:
+ JackNoteOffAction(WeakPtr<JackDriver> driver, unsigned char note_num);
+
+ void execute(Timestamp time);
+
+private:
+ WeakPtr<JackDriver> _driver;
+ unsigned char _note_num;
+};
+
+
+} // namespace Machina
+
+#endif // MACHINA_JACKACTIONS_HPP
diff --git a/src/engine/machina/JackDriver.hpp b/src/engine/machina/JackDriver.hpp
new file mode 100644
index 0000000..84c9223
--- /dev/null
+++ b/src/engine/machina/JackDriver.hpp
@@ -0,0 +1,60 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 MACHINA_JACKDRIVER_HPP
+#define MACHINA_JACKDRIVER_HPP
+
+#include <raul/JackDriver.h>
+#include <raul/SharedPtr.h>
+#include <jack/midiport.h>
+#include "Machine.hpp"
+
+namespace Machina {
+
+
+class JackDriver : public Raul::JackDriver {
+public:
+ JackDriver();
+
+ void attach(const std::string& client_name);
+ void detach();
+
+ void set_machine(SharedPtr<Machine> machine) { _machine = machine; }
+
+ // Audio context
+ Timestamp stamp_to_offset(Timestamp stamp);
+ jack_port_t* output_port() { return _output_port; }
+ //Timestamp current_cycle_start() { return _current_cycle_start; }
+ //Timestamp current_cycle_offset() { return _current_cycle_offset; }
+ FrameCount current_cycle_nframes() { return _current_cycle_nframes; }
+
+
+protected:
+ virtual void on_process(jack_nframes_t nframes);
+
+private:
+ SharedPtr<Machine> _machine;
+ jack_port_t* _output_port;
+ Timestamp _current_cycle_start;
+ Timestamp _current_cycle_offset; ///< for split cycles
+ FrameCount _current_cycle_nframes;
+};
+
+
+} // namespace Machina
+
+#endif // MACHINA_JACKDRIVER_HPP
diff --git a/src/engine/machina/JackNodeFactory.hpp b/src/engine/machina/JackNodeFactory.hpp
new file mode 100644
index 0000000..017cc6d
--- /dev/null
+++ b/src/engine/machina/JackNodeFactory.hpp
@@ -0,0 +1,43 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 MACHINA_JACKNODEFACTORY_HPP
+#define MACHINA_JACKNODEFACTORY_HPP
+
+#include <raul/WeakPtr.h>
+#include "NodeFactory.hpp"
+
+namespace Machina {
+
+class JackDriver;
+
+
+class JackNodeFactory : public NodeFactory {
+public:
+ JackNodeFactory(WeakPtr<JackDriver> driver) : _driver(driver) {}
+
+ SharedPtr<Node> create_node(Node::ID id,
+ unsigned char note,
+ FrameCount duration);
+private:
+ WeakPtr<JackDriver> _driver;
+};
+
+
+} // namespace Machina
+
+#endif // MACHINA_JACKNODEFACTORY_HPP
diff --git a/src/engine/machina/Loader.hpp b/src/engine/machina/Loader.hpp
new file mode 100644
index 0000000..c3ce013
--- /dev/null
+++ b/src/engine/machina/Loader.hpp
@@ -0,0 +1,49 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 MACHINA_LOADER_HPP
+#define MACHINA_LOADER_HPP
+
+#include <glibmm/ustring.h>
+#include "raul/SharedPtr.h"
+#include "raul/Path.h"
+#include "raul/Namespaces.h"
+
+using Raul::Namespaces;
+
+namespace Machina {
+
+class Machine;
+class NodeFactory;
+
+
+class Loader {
+public:
+ Loader(SharedPtr<NodeFactory> node_factory,
+ SharedPtr<Namespaces> = SharedPtr<Namespaces>());
+
+ SharedPtr<Machine> load(const Glib::ustring& filename);
+
+private:
+ SharedPtr<NodeFactory> _node_factory;
+ SharedPtr<Namespaces> _namespaces;
+};
+
+
+} // namespace Machina
+
+#endif // MACHINA_LOADER_HPP
diff --git a/src/engine/machina/Machina.hpp b/src/engine/machina/Machina.hpp
new file mode 100644
index 0000000..6cefcc5
--- /dev/null
+++ b/src/engine/machina/Machina.hpp
@@ -0,0 +1,28 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <list>
+
+namespace Machina {
+
+class Machina {
+private:
+ std::list<Node> _nodes;
+};
+
+
+} // namespace Machina
diff --git a/src/engine/machina/Machine.hpp b/src/engine/machina/Machine.hpp
new file mode 100644
index 0000000..2ac739e
--- /dev/null
+++ b/src/engine/machina/Machine.hpp
@@ -0,0 +1,64 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef MACHINA_MACHINE_HPP
+#define MACHINA_MACHINE_HPP
+
+#include <vector>
+#include <map>
+#include "raul/SharedPtr.h"
+#include "types.hpp"
+#include "Node.hpp"
+
+namespace Machina {
+
+
+class Machine {
+public:
+ Machine();
+ ~Machine();
+
+ // Main context
+ void activate() { _is_activated = true; }
+ void deactivate() { _is_activated = false; }
+
+ void add_node(SharedPtr<Node> node);
+
+ // Audio context
+ void reset();
+ bool run(FrameCount nframes);
+
+ // Any context
+ FrameCount time() { return _time; }
+
+private:
+ typedef std::vector<SharedPtr<Node> > Nodes;
+
+ // Audio context
+ SharedPtr<Node> earliest_node() const;
+ void exit_node(const SharedPtr<Node>);
+
+ bool _is_activated;
+ bool _is_finished;
+ FrameCount _time;
+ Nodes _nodes;
+};
+
+
+} // namespace Machina
+
+#endif // MACHINA_MACHINE_HPP
diff --git a/src/engine/machina/Makefile.am b/src/engine/machina/Makefile.am
new file mode 100644
index 0000000..eca6f9b
--- /dev/null
+++ b/src/engine/machina/Makefile.am
@@ -0,0 +1,12 @@
+libmachinaincludedir = $(includedir)/machina
+
+libmachinainclude_HEADERS = \
+ types.hpp \
+ Node.hpp \
+ Edge.hpp \
+ Machine.hpp \
+ Loader.hpp \
+ JackDriver.hpp \
+ JackActions.hpp \
+ NodeFactory.hpp \
+ JackNodeFactory.hpp
diff --git a/src/engine/machina/Node.hpp b/src/engine/machina/Node.hpp
new file mode 100644
index 0000000..d0e19db
--- /dev/null
+++ b/src/engine/machina/Node.hpp
@@ -0,0 +1,82 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef MACHINA_NODE_HPP
+#define MACHINA_NODE_HPP
+
+#include <boost/utility.hpp>
+#include <raul/SharedPtr.h>
+#include <raul/List.h>
+#include "types.hpp"
+#include "Action.hpp"
+
+namespace Machina {
+
+class Edge;
+
+
+/** A node is a state (as in a FSM diagram), or "note".
+ *
+ * It contains a action, as well as a duration and pointers to it's
+ * successors (states/nodes that (may) follow it).
+ *
+ * Initial nodes do not have enter actions (since they are entered at
+ * an undefined point in time <= 0).
+ */
+class Node : public boost::noncopyable {
+public:
+ typedef std::string ID;
+
+ Node(FrameCount duration=0, bool initial=false);
+
+ void add_enter_action(Action* action);
+ void remove_enter_action(Action* action);
+
+ void add_exit_action(Action* action);
+ void remove_exit_action(Action* action);
+
+ void enter(Timestamp time);
+ void exit(Timestamp time);
+
+ void add_outgoing_edge(SharedPtr<Edge> edge);
+ void remove_outgoing_edge(SharedPtr<Edge> edge);
+
+ bool is_initial() const { return _is_initial; }
+ void set_initial(bool i) { _is_initial = i; }
+ bool is_active() const { return _is_active; }
+ Timestamp enter_time() const { return _enter_time; }
+ Timestamp exit_time() const { return _enter_time + _duration; }
+ FrameCount duration() { return _duration; }
+ void set_duration(FrameCount d) { _duration = d; }
+
+ typedef Raul::List<SharedPtr<Edge> > EdgeList;
+ const EdgeList& outgoing_edges() const { return _outgoing_edges; }
+
+private:
+ bool _is_initial;
+ bool _is_active;
+ Timestamp _enter_time; ///< valid iff _is_active
+ FrameCount _duration;
+ Action* _enter_action;
+ Action* _exit_action;
+ EdgeList _outgoing_edges;
+};
+
+
+} // namespace Machina
+
+#endif // MACHINA_NODE_HPP
diff --git a/src/engine/machina/NodeFactory.hpp b/src/engine/machina/NodeFactory.hpp
new file mode 100644
index 0000000..f38fd92
--- /dev/null
+++ b/src/engine/machina/NodeFactory.hpp
@@ -0,0 +1,40 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 MACHINA_NODEFACTORY_HPP
+#define MACHINA_NODEFACTORY_HPP
+
+#include <raul/SharedPtr.h>
+#include "types.hpp"
+#include "Node.hpp"
+
+namespace Machina {
+
+
+class NodeFactory {
+public:
+ virtual ~NodeFactory() {}
+
+ virtual SharedPtr<Node> create_node(Node::ID id,
+ unsigned char note,
+ FrameCount duration) = 0;
+};
+
+
+} // namespace Machina
+
+#endif // MACHINA_NODEFACTORY_HPP
diff --git a/src/engine/machina/types.hpp b/src/engine/machina/types.hpp
new file mode 100644
index 0000000..8793fb1
--- /dev/null
+++ b/src/engine/machina/types.hpp
@@ -0,0 +1,31 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave 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 2 of the License, or (at your option) 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 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 Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef MACHINA_TYPES_HPP
+#define MACHINA_TYPES_HPP
+
+#include <jack/types.h>
+
+namespace Machina {
+
+
+typedef jack_nframes_t FrameCount;
+typedef jack_nframes_t Timestamp;
+
+} // namespace Machina
+
+#endif // MACHINA_TYPES_HPP