From bd92c37ed3513ab881cad3e8667c6e9c6af0858f Mon Sep 17 00:00:00 2001
From: David Robillard <d@drobilla.net>
Date: Sat, 9 Feb 2008 18:23:57 +0000
Subject: Use Raul::TimeStamp (LV2 compatible typed 32:32 fixed timestamp)
 everywhere. Fix initial size of Patchage messages window. Machina disabled
 for now (transitioning to generic timestamps).

git-svn-id: http://svn.drobilla.net/lad/machina@1133 a436a847-0d15-0410-975c-d299462d15a1
---
 src/engine/Engine.cpp                 |  4 +--
 src/engine/JackDriver.cpp             | 30 ++++++++++++++---------
 src/engine/LearnRequest.cpp           |  4 +--
 src/engine/Loader.cpp                 | 10 +++++---
 src/engine/Machine.cpp                | 28 ++++++++++-----------
 src/engine/MachineBuilder.cpp         | 46 +++++++++++++++++------------------
 src/engine/MidiAction.cpp             |  2 +-
 src/engine/Mutation.cpp               |  2 +-
 src/engine/Node.cpp                   | 12 ++++-----
 src/engine/Recorder.cpp               | 12 ++++-----
 src/engine/SMFDriver.cpp              | 36 ++++++++++++++-------------
 src/engine/machina/Action.hpp         |  4 +--
 src/engine/machina/Driver.hpp         |  2 +-
 src/engine/machina/Engine.hpp         |  3 +--
 src/engine/machina/JackDriver.hpp     | 14 +++++------
 src/engine/machina/LearnRequest.hpp   | 10 +++++---
 src/engine/machina/Machine.hpp        | 10 ++++----
 src/engine/machina/MachineBuilder.hpp | 21 ++++++++--------
 src/engine/machina/MidiAction.hpp     |  2 +-
 src/engine/machina/Node.hpp           | 33 +++++++++++++------------
 src/engine/machina/Recorder.hpp       | 13 +++++-----
 src/engine/machina/SMFDriver.hpp      | 16 ++++++------
 22 files changed, 161 insertions(+), 153 deletions(-)

(limited to 'src/engine')

diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp
index 1a2fe56..0724018 100644
--- a/src/engine/Engine.cpp
+++ b/src/engine/Engine.cpp
@@ -67,10 +67,10 @@ Engine::import_machine(const Glib::ustring& uri)
  * Safe to call while engine is processing.
  */
 SharedPtr<Machine>
-Engine::import_midi(const Glib::ustring& uri, Raul::BeatTime duration)
+Engine::import_midi(const Glib::ustring& uri, Raul::TimeStamp q, Raul::TimeDuration duration)
 {
 	SharedPtr<SMFDriver> file_driver(new SMFDriver());
-	SharedPtr<Machine> m = file_driver->learn(uri, duration);
+	SharedPtr<Machine> m = file_driver->learn(uri, q, duration);
 	m->activate();
 	_driver->machine()->nodes().append(m->nodes());
 	
diff --git a/src/engine/JackDriver.cpp b/src/engine/JackDriver.cpp
index 2e588ec..5560926 100644
--- a/src/engine/JackDriver.cpp
+++ b/src/engine/JackDriver.cpp
@@ -35,11 +35,10 @@ JackDriver::JackDriver(SharedPtr<Machine> machine)
 	, _output_port(NULL)
 	, _cycle_time(1/48000.0, 120.0)
 	, _bpm(120.0)
-	, _quantization(0.0)
+	, _quantization(machine->time().unit())
+	, _record_time(machine->time().unit())
 	, _recording(0)
 {
-	if (!_machine)
-		_machine = SharedPtr<Machine>(new Machine());
 }
 
 
@@ -74,6 +73,10 @@ JackDriver::attach(const std::string& client_name)
 		if (!_output_port)
 			std::cerr << "WARNING: Failed to create MIDI output port." << std::endl;
 
+		if (!_machine)
+			_machine = SharedPtr<Machine>(new Machine(
+					TimeUnit::frames(jack_get_sample_rate(jack_client()))));
+
 		_machine->activate();
 	}
 }
@@ -119,12 +122,12 @@ void
 JackDriver::process_input(SharedPtr<Machine> machine, const TimeSlice& time)
 {
 	// We only actually read Jack input at the beginning of a cycle
-	assert(time.offset_ticks() == 0);
+	assert(time.offset_ticks().is_zero());
 	assert(_input_port);
 
 	if (_recording.get()) {
 
-		const jack_nframes_t nframes     = time.length_ticks();
+		const jack_nframes_t nframes     = time.length_ticks().ticks();
 		void*                jack_buffer = jack_port_get_buffer(_input_port, nframes);
 		const jack_nframes_t event_count = jack_midi_get_event_count(jack_buffer);
 
@@ -132,7 +135,8 @@ JackDriver::process_input(SharedPtr<Machine> machine, const TimeSlice& time)
 			jack_midi_event_t ev;
 			jack_midi_event_get(&ev, jack_buffer, i);
 		
-			_recorder->write(_record_time + ev.time, ev.size, ev.buffer);
+			_recorder->write(_record_time + TimeStamp(_record_time.unit(), ev.time, 0),
+					ev.size, ev.buffer);
 		}
 
 		if (event_count > 0)
@@ -140,7 +144,7 @@ JackDriver::process_input(SharedPtr<Machine> machine, const TimeSlice& time)
 
 	} else {
 
-		const jack_nframes_t nframes     = time.length_ticks();
+		const jack_nframes_t nframes     = time.length_ticks().ticks();
 		void*                jack_buffer = jack_port_get_buffer(_input_port, nframes);
 		const jack_nframes_t event_count = jack_midi_get_event_count(jack_buffer);
 
@@ -154,7 +158,8 @@ JackDriver::process_input(SharedPtr<Machine> machine, const TimeSlice& time)
 				if (learn) {
 					learn->enter_action()->set_event(ev.size, ev.buffer);
 					learn->start(_quantization.get(),
-						time.ticks_to_beats(jack_last_frame_time(_client) + ev.time));
+							TimeStamp(TimeUnit::frames(sample_rate()),
+								jack_last_frame_time(_client) + ev.time, 0));
 				}
 
 			} else if (ev.buffer[0] == 0x80) {
@@ -165,7 +170,8 @@ JackDriver::process_input(SharedPtr<Machine> machine, const TimeSlice& time)
 					if (learn->started()) {
 						learn->exit_action()->set_event(ev.size, ev.buffer);
 						learn->finish(
-							time.ticks_to_beats(jack_last_frame_time(_client) + ev.time));
+							TimeStamp(TimeUnit::frames(sample_rate()),
+								jack_last_frame_time(_client) + ev.time, 0));
 						machine->clear_pending_learn();
 					}
 				}
@@ -177,9 +183,9 @@ JackDriver::process_input(SharedPtr<Machine> machine, const TimeSlice& time)
 
 
 void
-JackDriver::write_event(Raul::BeatTime time,
-                        size_t         size,
-                        const byte*    event) throw (std::logic_error)
+JackDriver::write_event(Raul::TimeStamp time,
+                        size_t          size,
+                        const byte*     event) throw (std::logic_error)
 {
 	if (!_output_port)
 		return;
diff --git a/src/engine/LearnRequest.cpp b/src/engine/LearnRequest.cpp
index f4d88f0..2bcd719 100644
--- a/src/engine/LearnRequest.cpp
+++ b/src/engine/LearnRequest.cpp
@@ -23,12 +23,12 @@ namespace Machina {
 
 /** Add the learned actions to the node */
 void
-LearnRequest::finish(BeatTime time)
+LearnRequest::finish(TimeStamp time)
 {
 	_node->set_enter_action(_enter_action);
 	_node->set_exit_action(_exit_action);
 
-	double duration = Raul::Quantizer::quantize(_quantization, time - _start_time);
+	TimeDuration duration = Raul::Quantizer::quantize(_quantization, time - _start_time);
 	
 	_node->set_duration(duration);
 }
diff --git a/src/engine/Loader.cpp b/src/engine/Loader.cpp
index cf41bd1..3cc93aa 100644
--- a/src/engine/Loader.cpp
+++ b/src/engine/Loader.cpp
@@ -74,7 +74,7 @@ Loader::load(const Glib::ustring& uri)
 
 	cout << "[Loader] Loading " << machine_uri << " from " << document_uri << endl;
 
-	machine = SharedPtr<Machine>(new Machine());
+	machine = SharedPtr<Machine>(new Machine(TimeUnit::beats(LV2_EVENT_PPQN)));
 	
 	typedef std::map<string, SharedPtr<Node> > Created;
 	Created created;
@@ -93,7 +93,9 @@ Loader::load(const Glib::ustring& uri)
 
 	for (Query::Results::iterator i = results.begin(); i != results.end(); ++i) {
 		const char* node_id = (*i)["node"];
-		SharedPtr<Node> node(new Node(float((*i)["duration"]), true));
+		SharedPtr<Node> node(new Node(
+				TimeStamp(TimeUnit(TimeUnit::BEATS, LV2_EVENT_PPQN), (double)(*i)["duration"]),
+				true));
 		machine->add_node(node);
 		created[node_id] = node;
 	}
@@ -112,7 +114,9 @@ Loader::load(const Glib::ustring& uri)
 	for (Query::Results::iterator i = results.begin(); i != results.end(); ++i) {
 		const char* node_id = (*i)["node"];
 		if (created.find(node_id) == created.end()) {
-			SharedPtr<Node> node(new Node((float)(*i)["duration"], false));
+			SharedPtr<Node> node(new Node(
+				TimeStamp(TimeUnit(TimeUnit::BEATS, LV2_EVENT_PPQN), (double)(*i)["duration"]),
+				false));
 			machine->add_node(node); 
 			created[node_id] = node;
 		}
diff --git a/src/engine/Machine.cpp b/src/engine/Machine.cpp
index 3a1283d..23bf1f8 100644
--- a/src/engine/Machine.cpp
+++ b/src/engine/Machine.cpp
@@ -30,11 +30,11 @@ using namespace Raul;
 namespace Machina {
 
 
-Machine::Machine()
+Machine::Machine(TimeUnit unit)
 	: _active_nodes(MAX_ACTIVE_NODES, SharedPtr<Node>())
 	, _is_activated(false)
 	, _is_finished(false)
-	, _time(0)
+	, _time(unit)
 {
 }
 
@@ -49,7 +49,7 @@ Machine::Machine(const Machine& copy)
 	, _active_nodes(MAX_ACTIVE_NODES, SharedPtr<Node>())
 	, _is_activated(false)
 	, _is_finished(false)
-	, _time(0)
+	, _time(copy.time().unit())
 	, _sink(copy._sink)
 {
 	map< SharedPtr<Node>, SharedPtr<Node> > replacements;
@@ -165,7 +165,7 @@ Machine::remove_node(SharedPtr<Node> node)
 /** Exit all active states and reset time to 0.
  */
 void
-Machine::reset(Raul::BeatTime time)
+Machine::reset(Raul::TimeStamp time)
 {
 	if (!_is_finished) {
 		for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) {
@@ -299,27 +299,26 @@ Machine::exit_node(SharedPtr<Raul::MIDISink> sink, SharedPtr<Node> node)
  * machine actually finished on (so it can be restarted immediately
  * with sample accuracy if necessary).
  */
-BeatCount
+TimeDuration
 Machine::run(const Raul::TimeSlice& time)
 {
 	if (_is_finished)
-		return 0;
+		return TimeDuration(_time.unit(), 0, 0);
 
 	SharedPtr<Raul::MIDISink> sink = _sink.lock();
 
-	const TickTime  cycle_end_ticks = time.start_ticks() + time.length_ticks() - 1;
-	const BeatCount cycle_end_beats = time.ticks_to_beats(cycle_end_ticks);
+	const TimeStamp cycle_end = time.start_ticks() + time.length_ticks();
 
 	assert(_is_activated);
 
 	// Initial run, enter all initial states
-	if (_time == 0) {
+	if (_time.is_zero()) {
 		bool entered = false;
 		if ( ! _nodes.empty()) {
 			for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) {
 				
 				if ((*n)->is_active())
-					(*n)->exit(sink, 0);
+					(*n)->exit(sink, _time);
 				
 				if ((*n)->is_initial()) {
 					if (enter_node(sink, (*n)))
@@ -330,11 +329,11 @@ Machine::run(const Raul::TimeSlice& time)
 		}
 		if (!entered) {
 			_is_finished = true;
-			return 0;
+			return TimeStamp(_time.unit(), 0, 0);
 		}
 	}
 	
-	BeatCount this_time = 0;
+	TimeStamp this_time(_time.unit(), 0, 0);
 
 	while (true) {
 
@@ -350,8 +349,7 @@ Machine::run(const Raul::TimeSlice& time)
 			break;
 
 		// Earliest active state ends this cycle
-		} else if (time.beats_to_ticks(earliest->exit_time())
-				<= cycle_end_ticks) {
+		} else if (earliest->exit_time() <= cycle_end) {
 			this_time += earliest->exit_time() - _time;
 			_time = time.ticks_to_beats(
 					time.beats_to_ticks(earliest->exit_time()));
@@ -359,7 +357,7 @@ Machine::run(const Raul::TimeSlice& time)
 
 		// Earliest active state ends in the future, done this cycle
 		} else {
-			_time = cycle_end_beats;
+			_time = cycle_end;
 			this_time = time.length_beats(); // ran the entire cycle
 			break;
 		}
diff --git a/src/engine/MachineBuilder.cpp b/src/engine/MachineBuilder.cpp
index 34e45b8..206df5d 100644
--- a/src/engine/MachineBuilder.cpp
+++ b/src/engine/MachineBuilder.cpp
@@ -29,26 +29,24 @@ using namespace Raul;
 namespace Machina {
 
 
-MachineBuilder::MachineBuilder(SharedPtr<Machine> machine, Raul::BeatTime q)
+MachineBuilder::MachineBuilder(SharedPtr<Machine> machine, Raul::TimeStamp q)
 	: _quantization(q)
-	, _time(0)
+	, _time(machine->time().unit()) // = 0
 	, _machine(machine)
-	, _initial_node(new Node())
+	, _initial_node(new Node(_time, true)) // duration 0
 	, _connect_node(_initial_node)
-	, _connect_node_end_time(0)
+	, _connect_node_end_time(_time) // = 0
 {
-	_initial_node->set_initial(true);
 }
 
 
 void
 MachineBuilder::reset()
 {
-	_initial_node = SharedPtr<Node>(new Node(0.0));
-	_initial_node->set_initial(true);
+	_time = TimeStamp(_machine->time().unit()); // = 0
+	_initial_node = SharedPtr<Node>(new Node(_time, true)); // duration 0
 	_connect_node = _initial_node;
-	_connect_node_end_time = 0;
-	_time = 0;
+	_connect_node_end_time = _time; // = 0
 }
 
 
@@ -65,12 +63,12 @@ MachineBuilder::is_delay_node(SharedPtr<Node> node) const
 /** Set the duration of a node, with quantization.
  */
 void
-MachineBuilder::set_node_duration(SharedPtr<Node> node, Raul::BeatTime d) const
+MachineBuilder::set_node_duration(SharedPtr<Node> node, Raul::TimeStamp d) const
 {
-	Raul::BeatTime q_dur = Quantizer::quantize(_quantization, d);
+	Raul::TimeStamp q_dur = Quantizer::quantize(_quantization, d);
 
 	// Never quantize a note to duration 0
-	if (q_dur == 0 && ( node->enter_action() || node->exit_action() ))
+	if (q_dur.is_zero() && ( node->enter_action() || node->exit_action() ))
 		q_dur = _quantization; // Round up
 
 	node->set_duration(q_dur);
@@ -83,8 +81,8 @@ MachineBuilder::set_node_duration(SharedPtr<Node> node, Raul::BeatTime d) const
  */
 SharedPtr<Node>
 MachineBuilder::connect_nodes(SharedPtr<Machine> m,
-                              SharedPtr<Node>    tail, Raul::BeatTime tail_end_time,
-                              SharedPtr<Node>    head, Raul::BeatTime head_start_time)
+                              SharedPtr<Node>    tail, Raul::TimeStamp tail_end_time,
+                              SharedPtr<Node>    head, Raul::TimeStamp head_start_time)
 {
 	assert(tail != head);
 	assert(head_start_time >= tail_end_time);
@@ -100,8 +98,7 @@ MachineBuilder::connect_nodes(SharedPtr<Machine> m,
 		tail->add_edge(SharedPtr<Edge>(new Edge(tail, head)));
 	} else {
 		// Need to actually create a delay node
-		delay_node = SharedPtr<Node>(new Node());
-		set_node_duration(delay_node, head_start_time - tail_end_time);
+		delay_node = SharedPtr<Node>(new Node(head_start_time - tail_end_time));
 		tail->add_edge(SharedPtr<Edge>(new Edge(tail, delay_node)));
 		delay_node->add_edge(SharedPtr<Edge>(new Edge(delay_node, head)));
 		m->add_node(delay_node);
@@ -112,22 +109,23 @@ MachineBuilder::connect_nodes(SharedPtr<Machine> m,
 
 
 void
-MachineBuilder::event(Raul::BeatTime time_offset,
-                      size_t         ev_size,
-                      unsigned char* buf)
+MachineBuilder::event(Raul::TimeStamp time_offset,
+                      size_t          ev_size,
+                      unsigned char*  buf)
 {
-	Raul::BeatTime t = _time + time_offset;
+	const Raul::TimeUnit unit = time_offset.unit();
+	Raul::TimeStamp t = _time + time_offset;
 
 	if (ev_size == 0)
 		return;
 
 	if ((buf[0] & 0xF0) == MIDI_CMD_NOTE_ON) {
 		
-		SharedPtr<Node> node(new Node(0.0));
+		SharedPtr<Node> node(new Node(TimeStamp(unit)));
 		node->set_enter_action(SharedPtr<Action>(new MidiAction(ev_size, buf)));
 
 		SharedPtr<Node> this_connect_node;
-		Raul::BeatTime  this_connect_node_end_time;
+		Raul::TimeStamp this_connect_node_end_time(unit);
 
 		// If currently polyphonic, use a poly node with no successors as connect node
 		// Results in patterns closes to what a human would choose
@@ -187,7 +185,7 @@ MachineBuilder::event(Raul::BeatTime time_offset,
 					// Finish a polyphonic section
 					if (_poly_nodes.size() > 0) {
 
-						_connect_node = SharedPtr<Node>(new Node(0.0));
+						_connect_node = SharedPtr<Node>(new Node(TimeStamp(unit)));
 						_machine->add_node(_connect_node);
 
 						connect_nodes(_machine, resolved, t, _connect_node, t);
@@ -206,7 +204,7 @@ MachineBuilder::event(Raul::BeatTime time_offset,
 					} else {
 						
 						// Trim useless delay node if possible (these appear after poly sections)
-						if (is_delay_node(_connect_node) && _connect_node->duration() == 0
+						if (is_delay_node(_connect_node) && _connect_node->duration().is_zero()
 								&& _connect_node->edges().size() == 1
 								&& (*_connect_node->edges().begin())->head() == resolved) {
 
diff --git a/src/engine/MidiAction.cpp b/src/engine/MidiAction.cpp
index b17c5b9..bad3fc0 100644
--- a/src/engine/MidiAction.cpp
+++ b/src/engine/MidiAction.cpp
@@ -78,7 +78,7 @@ MidiAction::set_event(size_t size, const byte* new_event)
  * Safe to call concurrently with set_event.
  */
 void
-MidiAction::execute(SharedPtr<Raul::MIDISink> sink, Raul::BeatTime time)
+MidiAction::execute(SharedPtr<Raul::MIDISink> sink, Raul::TimeStamp time)
 {
 	const byte* const event = _event.get();
 
diff --git a/src/engine/Mutation.cpp b/src/engine/Mutation.cpp
index a307ce5..8c8c245 100644
--- a/src/engine/Mutation.cpp
+++ b/src/engine/Mutation.cpp
@@ -52,7 +52,7 @@ AddNode::mutate(Machine& machine)
 	//cout << "ADD NODE" << endl;
 
 	// Create random node
-	SharedPtr<Node> node(new Node());
+	SharedPtr<Node> node(new Node(machine.time().unit()));
 	node->set_selector(true);
 	
 	SharedPtr<Node> note_node = machine.random_node();
diff --git a/src/engine/Node.cpp b/src/engine/Node.cpp
index 56bfac5..f24c4be 100644
--- a/src/engine/Node.cpp
+++ b/src/engine/Node.cpp
@@ -29,11 +29,11 @@ using namespace Raul;
 namespace Machina {
 
 
-Node::Node(BeatCount duration, bool initial)
+Node::Node(TimeDuration duration, bool initial)
 	: _is_initial(initial)
 	, _is_selector(false)
 	, _is_active(false)
-	, _enter_time(0)
+	, _enter_time(duration.unit())
 	, _duration(duration)
 {
 }
@@ -44,7 +44,7 @@ Node::Node(const Node& copy)
 	, _is_initial(copy._is_initial)
 	, _is_selector(copy._is_selector)
 	, _is_active(false)
-	, _enter_time(0)
+	, _enter_time(copy.enter_time())
 	, _duration(copy._duration)
 	, _enter_action(ActionFactory::copy(copy._enter_action))
 	, _exit_action(ActionFactory::copy(copy._exit_action))
@@ -126,7 +126,7 @@ Node::set_exit_action(SharedPtr<Action> action)
 
 
 void
-Node::enter(SharedPtr<MIDISink> sink, BeatTime time)
+Node::enter(SharedPtr<MIDISink> sink, TimeStamp time)
 {
 	assert(!_is_active);
 	
@@ -140,7 +140,7 @@ Node::enter(SharedPtr<MIDISink> sink, BeatTime time)
 
 
 void
-Node::exit(SharedPtr<MIDISink> sink, BeatTime time)
+Node::exit(SharedPtr<MIDISink> sink, TimeStamp time)
 {
 	assert(_is_active);
 	
@@ -221,7 +221,7 @@ Node::write_state(Redland::Model& model)
 
 	model.add_statement(_id,
 			"machina:duration",
-			AtomRDF::atom_to_node(model.world(), Atom((float)_duration)));
+			AtomRDF::atom_to_node(model.world(), Atom((float)_duration.to_double())));
 
 	if (_enter_action) {
 		_enter_action->write_state(model);
diff --git a/src/engine/Recorder.cpp b/src/engine/Recorder.cpp
index 1fd8ee4..302a66e 100644
--- a/src/engine/Recorder.cpp
+++ b/src/engine/Recorder.cpp
@@ -26,10 +26,10 @@ using namespace Raul;
 namespace Machina {
 
 
-Recorder::Recorder(size_t buffer_size, double tick_rate, double q)
-	: _tick_rate(tick_rate)
+Recorder::Recorder(size_t buffer_size, TimeUnit unit, TimeStamp q)
+	: _unit(unit)
 	, _record_buffer(buffer_size)
-	, _builder(new MachineBuilder(SharedPtr<Machine>(new Machine()), q))
+	, _builder(new MachineBuilder(SharedPtr<Machine>(new Machine(unit)), q))
 {
 }
 
@@ -37,13 +37,13 @@ Recorder::Recorder(size_t buffer_size, double tick_rate, double q)
 void
 Recorder::_whipped()
 {
-	TickTime      t;
+	TimeStamp     t(_unit);
 	size_t        size;
 	unsigned char buf[4];
 
 	while (_record_buffer.read(&t, &size, buf)) {
-		_builder->set_time(t * _tick_rate);
-		_builder->event(0, size, buf);
+		_builder->set_time(t);
+		_builder->event(TimeStamp(_unit), size, buf);
 	}
 } 
 
diff --git a/src/engine/SMFDriver.cpp b/src/engine/SMFDriver.cpp
index 85aa8ab..776339c 100644
--- a/src/engine/SMFDriver.cpp
+++ b/src/engine/SMFDriver.cpp
@@ -34,7 +34,7 @@ namespace Machina {
 SMFDriver::SMFDriver(SharedPtr<Machine> machine)
 	: Driver(machine)
 {
-	_writer = SharedPtr<Raul::SMFWriter>(new Raul::SMFWriter());
+	_writer = SharedPtr<Raul::SMFWriter>(new Raul::SMFWriter(machine->time().unit()));
 }
 
 
@@ -46,9 +46,10 @@ SMFDriver::SMFDriver(SharedPtr<Machine> machine)
  * @return the resulting machine.
  */
 SharedPtr<Machine>
-SMFDriver::learn(const string& filename, unsigned track, double q, Raul::BeatTime max_duration)
+SMFDriver::learn(const string& filename, unsigned track, Raul::TimeStamp q, Raul::TimeDuration max_duration)
 {
-	SharedPtr<Machine> m(new Machine());
+	assert(q.unit() == max_duration.unit());
+	SharedPtr<Machine> m(new Machine(max_duration.unit()));
 	SharedPtr<MachineBuilder> builder = SharedPtr<MachineBuilder>(new MachineBuilder(m, q));
 	Raul::SMFReader reader;
 	
@@ -76,9 +77,9 @@ SMFDriver::learn(const string& filename, unsigned track, double q, Raul::BeatTim
  * This will result in one disjoint subgraph in the machine for each track.
  */
 SharedPtr<Machine>
-SMFDriver::learn(const string& filename, double q, Raul::BeatTime max_duration)
+SMFDriver::learn(const string& filename, Raul::TimeStamp q, Raul::TimeStamp max_duration)
 {
-	SharedPtr<Machine> m(new Machine());
+	SharedPtr<Machine> m(new Machine(q.unit()));
 	SharedPtr<MachineBuilder> builder = SharedPtr<MachineBuilder>(new MachineBuilder(m, q));
 	Raul::SMFReader reader;
 	
@@ -105,29 +106,29 @@ void
 SMFDriver::learn_track(SharedPtr<MachineBuilder> builder,
                        Raul::SMFReader&          reader,
                        unsigned                  track,
-                       double                    q,
-                       Raul::BeatTime            max_duration)
+                       Raul::TimeStamp           q,
+                       Raul::TimeDuration        max_duration)
 {
 	const bool found_track = reader.seek_to_track(track);
 	if (!found_track)
 		return;
 
-	Raul::BeatTime unquantized_t = 0;
-	Raul::BeatTime t = 0;
-	unsigned char  buf[4];
-	uint32_t       ev_size;
-	uint32_t       ev_time;
+	Raul::TimeStamp unquantized_t(q.unit(), 0, 0);
+	Raul::TimeStamp t(q.unit(), 0, 0);
+	unsigned char   buf[4];
+	uint32_t        ev_size;
+	Raul::TimeStamp ev_time(q.unit());
 	while (reader.read_event(4, buf, &ev_size, &ev_time) >= 0) {
-		unquantized_t += ev_time / (double)reader.ppqn();
+		unquantized_t += ev_time;
 		t = Raul::Quantizer::quantize(q, unquantized_t);
 
 		builder->set_time(t);
 
-		if (max_duration != 0 && t > max_duration)
+		if ((!max_duration.is_zero()) && t > max_duration)
 			break;
 
 		if (ev_size > 0)
-			builder->event(0, ev_size, buf);
+			builder->event(TimeStamp(t.unit(), 0, 0), ev_size, buf);
 	}
 
 	builder->resolve();
@@ -135,9 +136,10 @@ SMFDriver::learn_track(SharedPtr<MachineBuilder> builder,
 
 
 void
-SMFDriver::run(SharedPtr<Machine> machine, Raul::BeatTime max_time)
+SMFDriver::run(SharedPtr<Machine> machine, Raul::TimeStamp max_time)
 {
-	Raul::TimeSlice time(1.0/(double)_writer->ppqn(), 120);
+	// FIXME: unit kludge (tempo only)
+	Raul::TimeSlice time(1.0/(double)_writer->unit().ppt(), 120);
 	time.set_length(time.beats_to_ticks(max_time));
 	machine->set_sink(shared_from_this());
 	machine->run(time);
diff --git a/src/engine/machina/Action.hpp b/src/engine/machina/Action.hpp
index 3cab3ee..1d1700d 100644
--- a/src/engine/machina/Action.hpp
+++ b/src/engine/machina/Action.hpp
@@ -32,7 +32,7 @@ namespace Machina {
 /** An Action, executed on entering or exiting of a state.
  */
 struct Action : public Raul::Deletable, public Raul::Stateful {
-	virtual void execute(SharedPtr<Raul::MIDISink> sink, Raul::BeatTime time) = 0;
+	virtual void execute(SharedPtr<Raul::MIDISink> sink, Raul::TimeStamp time) = 0;
 
 	virtual void write_state(Redland::Model& model);
 };
@@ -42,7 +42,7 @@ class PrintAction : public Action {
 public:
 	PrintAction(const std::string& msg) : _msg(msg) {}
 
-	void execute(SharedPtr<Raul::MIDISink>, Raul::BeatTime time)
+	void execute(SharedPtr<Raul::MIDISink>, Raul::TimeStamp time)
 	{ std::cout << "t=" << time << ": " << _msg << std::endl; }
 
 private:
diff --git a/src/engine/machina/Driver.hpp b/src/engine/machina/Driver.hpp
index e497356..31d8a9c 100644
--- a/src/engine/machina/Driver.hpp
+++ b/src/engine/machina/Driver.hpp
@@ -34,7 +34,7 @@ public:
 	virtual void set_machine(SharedPtr<Machine> machine) { _machine = machine; }
 	
 	virtual void set_bpm(double bpm) = 0;
-	virtual void set_quantization(double quantization) = 0;
+	virtual void set_quantization(Raul::TimeStamp q) = 0;
 	
 	virtual void activate() {}
 	virtual void deactivate() {}
diff --git a/src/engine/machina/Engine.hpp b/src/engine/machina/Engine.hpp
index effa4be..763b9a8 100644
--- a/src/engine/machina/Engine.hpp
+++ b/src/engine/machina/Engine.hpp
@@ -20,7 +20,6 @@
 
 #include <glibmm/ustring.h>
 #include <raul/SharedPtr.hpp>
-#include <raul/types.hpp>
 #include "machina/Driver.hpp"
 #include "machina/Loader.hpp"
 
@@ -45,7 +44,7 @@ public:
 
 	SharedPtr<Machine> load_machine(const Glib::ustring& uri);
 	SharedPtr<Machine> import_machine(const Glib::ustring& uri);
-	SharedPtr<Machine> import_midi(const Glib::ustring& uri, Raul::BeatTime d);
+	SharedPtr<Machine> import_midi(const Glib::ustring& uri, Raul::TimeStamp q, Raul::TimeDuration d);
 
 	void set_bpm(double bpm);
 	void set_quantization(double beat_fraction);
diff --git a/src/engine/machina/JackDriver.hpp b/src/engine/machina/JackDriver.hpp
index 017d867..7fb5351 100644
--- a/src/engine/machina/JackDriver.hpp
+++ b/src/engine/machina/JackDriver.hpp
@@ -22,7 +22,7 @@
 #include <raul/JackDriver.hpp>
 #include <raul/SharedPtr.hpp>
 #include <raul/DoubleBuffer.hpp>
-#include <raul/StampedChunkRingBuffer.hpp>
+#include <raul/EventRingBuffer.hpp>
 #include <raul/Semaphore.hpp>
 #include <raul/Command.hpp>
 #include <jack/midiport.h>
@@ -56,12 +56,12 @@ public:
 
 	void set_machine(SharedPtr<Machine> machine);
 	
-	void write_event(Raul::BeatTime       time,
+	void write_event(Raul::TimeStamp      time,
 	                 size_t               size,
 	                 const unsigned char* event) throw (std::logic_error);
 	
-	void set_bpm(double bpm)                   { _bpm.set(bpm); }
-	void set_quantization(double quantization) { _quantization.set(quantization); }
+	void set_bpm(double bpm)                 { _bpm.set(bpm); }
+	void set_quantization(Raul::TimeStamp q) { _quantization.set(q); }
 
 	void stop();
 
@@ -83,12 +83,12 @@ private:
 	
 	Raul::TimeSlice _cycle_time;
 
-	Raul::DoubleBuffer<double> _bpm;
-	Raul::DoubleBuffer<double> _quantization;
+	Raul::DoubleBuffer<double>          _bpm;
+	Raul::DoubleBuffer<Raul::TimeStamp> _quantization;
 
 	Raul::Command _stop;
 
-	Raul::TickTime      _record_time;
+	Raul::TimeStamp     _record_time;
 	Raul::AtomicInt     _recording;
 	SharedPtr<Recorder> _recorder;
 };
diff --git a/src/engine/machina/LearnRequest.hpp b/src/engine/machina/LearnRequest.hpp
index f6bc60f..1d36057 100644
--- a/src/engine/machina/LearnRequest.hpp
+++ b/src/engine/machina/LearnRequest.hpp
@@ -43,10 +43,10 @@ public:
 		return ret;
 	}
 
-	void start(double q, BeatTime time)
+	void start(TimeStamp q, Raul::TimeStamp time)
 		{ _started = true; _start_time = time; _quantization = q; }
 	
-	void finish(BeatTime time);
+	void finish(TimeStamp time);
 	
 	bool started() { return _started; }
 
@@ -57,6 +57,8 @@ public:
 private:
 	LearnRequest(SharedPtr<Raul::Maid> maid, SharedPtr<Node> node)
 		: _started(false)
+		, _start_time(TimeUnit(TimeUnit::BEATS, 19200), 0, 0) // irrelevant
+		, _quantization(TimeUnit(TimeUnit::BEATS, 19200), 1, 0) // irrelevant
 		, _node(node)
 		, _enter_action(new MidiAction(4, NULL))
 		, _exit_action(new MidiAction(4, NULL))
@@ -66,8 +68,8 @@ private:
 	}
 
 	bool                  _started;
-	BeatTime              _start_time;
-	double                _quantization;
+	TimeStamp             _start_time;
+	TimeStamp             _quantization;
 	SharedPtr<Node>       _node;
 	SharedPtr<MidiAction> _enter_action;
 	SharedPtr<MidiAction> _exit_action;
diff --git a/src/engine/machina/Machine.hpp b/src/engine/machina/Machine.hpp
index 5c4df36..dae8b75 100644
--- a/src/engine/machina/Machine.hpp
+++ b/src/engine/machina/Machine.hpp
@@ -36,7 +36,7 @@ namespace Machina {
  */
 class Machine : public Raul::Stateful {
 public:
-	Machine();
+	Machine(TimeUnit unit);
 	Machine(const Machine& copy);
 
 	Machine& operator=(const Machine& other);
@@ -59,11 +59,11 @@ public:
 	void write_state(Redland::Model& model);
 
 	// Audio context
-	void      reset(Raul::BeatTime time);
-	BeatCount run(const Raul::TimeSlice& time);
+	void         reset(Raul::TimeStamp time);
+	TimeDuration run(const Raul::TimeSlice& time);
 	
 	// Any context
-	inline Raul::BeatTime time() const { return _time; }
+	inline Raul::TimeStamp time() const { return _time; }
 
 	SharedPtr<LearnRequest> pending_learn() { return _pending_learn; }
 	void clear_pending_learn()              { _pending_learn.reset(); }
@@ -89,7 +89,7 @@ private:
 
 	bool                    _is_activated;
 	bool                    _is_finished;
-	Raul::BeatTime          _time;
+	Raul::TimeStamp         _time;
 	SharedPtr<LearnRequest> _pending_learn;
 	WeakPtr<Raul::MIDISink> _sink;
 	Nodes                   _nodes;
diff --git a/src/engine/machina/MachineBuilder.hpp b/src/engine/machina/MachineBuilder.hpp
index c7b5def..58d1eb4 100644
--- a/src/engine/machina/MachineBuilder.hpp
+++ b/src/engine/machina/MachineBuilder.hpp
@@ -19,7 +19,6 @@
 #define MACHINA_MACHINEBUILDER_HPP
 
 #include <list>
-#include <raul/types.hpp>
 #include <raul/SharedPtr.hpp>
 
 namespace Machina {
@@ -31,11 +30,11 @@ class Node;
 class MachineBuilder {
 public:
 	MachineBuilder(SharedPtr<Machine> machine,
-	               Raul::BeatTime     quantization);
+	               Raul::TimeStamp    quantization);
 
-	void set_time(Raul::BeatTime time) { _time = time; }
+	void set_time(Raul::TimeStamp time) { _time = time; }
 
-	void event(Raul::BeatTime time_offset, size_t size, unsigned char* buf);
+	void event(Raul::TimeStamp time_offset, size_t size, unsigned char* buf);
 	
 	void reset();
 	void resolve();
@@ -44,26 +43,26 @@ public:
 
 private:
 	bool is_delay_node(SharedPtr<Node> node) const;
-	void set_node_duration(SharedPtr<Node> node, Raul::BeatTime d) const;
+	void set_node_duration(SharedPtr<Node> node, Raul::TimeStamp d) const;
 
 	SharedPtr<Node>
 	connect_nodes(SharedPtr<Machine> m,
-                  SharedPtr<Node>    tail, Raul::BeatTime tail_end_time,
-     	          SharedPtr<Node>    head, Raul::BeatTime head_start_time);
+                  SharedPtr<Node>    tail, Raul::TimeStamp tail_end_time,
+     	          SharedPtr<Node>    head, Raul::TimeStamp head_start_time);
 	
 	typedef std::list<SharedPtr<Node> > ActiveList;
 	ActiveList _active_nodes;
 	
-	typedef std::list<std::pair<Raul::BeatTime, SharedPtr<Node> > > PolyList;
+	typedef std::list<std::pair<Raul::TimeStamp, SharedPtr<Node> > > PolyList;
 	PolyList _poly_nodes;
 
-	Raul::BeatTime     _quantization;
-	Raul::BeatTime     _time;
+	Raul::TimeStamp    _quantization;
+	Raul::TimeStamp    _time;
 
 	SharedPtr<Machine> _machine;
 	SharedPtr<Node>    _initial_node;
 	SharedPtr<Node>    _connect_node;
-	Raul::BeatTime     _connect_node_end_time;
+	Raul::TimeStamp    _connect_node_end_time;
 };
 
 
diff --git a/src/engine/machina/MidiAction.hpp b/src/engine/machina/MidiAction.hpp
index 1a3f176..57dd242 100644
--- a/src/engine/machina/MidiAction.hpp
+++ b/src/engine/machina/MidiAction.hpp
@@ -40,7 +40,7 @@ public:
 
 	bool set_event(size_t size, const byte* event);
 
-	void execute(SharedPtr<Raul::MIDISink> driver, Raul::BeatTime time);
+	void execute(SharedPtr<Raul::MIDISink> driver, Raul::TimeStamp time);
 	
 	virtual void write_state(Redland::Model& model);
 
diff --git a/src/engine/machina/Node.hpp b/src/engine/machina/Node.hpp
index 324ec29..446db96 100644
--- a/src/engine/machina/Node.hpp
+++ b/src/engine/machina/Node.hpp
@@ -28,8 +28,9 @@
 namespace Machina {
 
 class Edge;
-using Raul::BeatCount;
-using Raul::BeatTime;
+using Raul::TimeDuration;
+using Raul::TimeStamp;
+using Raul::TimeUnit;
 
 
 /** A node is a state (as in a FSM diagram), or "note".
@@ -44,7 +45,7 @@ class Node : public Raul::Stateful {
 public:
 	typedef std::string ID;
 
-	Node(BeatCount duration=1/2.0, bool initial=false);
+	Node(TimeDuration duration, bool initial=false);
 	Node(const Node& copy);
 
 	void set_enter_action(SharedPtr<Action> action);
@@ -53,8 +54,8 @@ public:
 	SharedPtr<Action> enter_action() { return _enter_action; }
 	SharedPtr<Action> exit_action()  { return _exit_action; }
 
-	void enter(SharedPtr<Raul::MIDISink> driver, BeatTime time);
-	void exit(SharedPtr<Raul::MIDISink> driver, BeatTime time);
+	void enter(SharedPtr<Raul::MIDISink> driver, TimeStamp time);
+	void exit(SharedPtr<Raul::MIDISink> driver, TimeStamp time);
 
 	void edges_changed();
 
@@ -65,15 +66,15 @@ public:
 
 	void write_state(Redland::Model& model);
 
-	bool      is_initial() const        { return _is_initial; }
-	void      set_initial(bool i)       { _is_initial = i; }
-	bool      is_active() const         { return _is_active; }
-	BeatTime  enter_time() const        { assert(_is_active); return _enter_time; }
-	BeatTime  exit_time() const         { assert(_is_active); return _enter_time + _duration; }
-	BeatCount duration()                { return _duration; }
-	void      set_duration(BeatCount d) { _duration = d; }
-	bool      is_selector() const       { return _is_selector; }
-	void      set_selector(bool i);
+	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           { assert(_is_active); return _enter_time; }
+	TimeStamp    exit_time() const            { assert(_is_active); return _enter_time + _duration; }
+	TimeDuration duration()                   { return _duration; }
+	void         set_duration(TimeDuration d) { _duration = d; }
+	bool         is_selector() const          { return _is_selector; }
+	void         set_selector(bool i);
 
 	inline bool changed()     { return _changed; }
 	inline void set_changed() { _changed = true; }
@@ -90,8 +91,8 @@ private:
 	bool              _is_initial;
 	bool              _is_selector;
 	bool              _is_active;
-	BeatTime          _enter_time; ///< valid iff _is_active
-	BeatCount         _duration;
+	TimeStamp         _enter_time; ///< valid iff _is_active
+	TimeDuration      _duration;
 	SharedPtr<Action> _enter_action;
 	SharedPtr<Action> _exit_action;
 	Edges             _edges;
diff --git a/src/engine/machina/Recorder.hpp b/src/engine/machina/Recorder.hpp
index 7938556..5afce2a 100644
--- a/src/engine/machina/Recorder.hpp
+++ b/src/engine/machina/Recorder.hpp
@@ -18,10 +18,9 @@
 #ifndef MACHINA_RECORDER_HPP
 #define MACHINA_RECORDER_HPP
 
-#include <raul/types.hpp>
 #include <raul/Slave.hpp>
 #include <raul/SharedPtr.hpp>
-#include <raul/StampedChunkRingBuffer.hpp>
+#include <raul/EventRingBuffer.hpp>
 #include "Machine.hpp"
 
 namespace Machina {
@@ -31,9 +30,9 @@ class MachineBuilder;
 
 class Recorder : public Raul::Slave {
 public:
-	Recorder(size_t buffer_size, double tick_rate, double q);
+	Recorder(size_t buffer_size, TimeUnit unit, TimeStamp q);
 
-	inline void write(Raul::TickTime time, size_t size, const unsigned char* buf) {
+	inline void write(Raul::TimeStamp time, size_t size, const unsigned char* buf) {
 		_record_buffer.write(time, size, buf);
 	}
 
@@ -42,9 +41,9 @@ public:
 private:
 	virtual void _whipped();
 	
-	double                       _tick_rate;
-	Raul::StampedChunkRingBuffer _record_buffer;
-	SharedPtr<MachineBuilder>    _builder;
+	TimeUnit                  _unit;
+	Raul::EventRingBuffer     _record_buffer;
+	SharedPtr<MachineBuilder> _builder;
 };
 
 
diff --git a/src/engine/machina/SMFDriver.hpp b/src/engine/machina/SMFDriver.hpp
index 55d76a0..73e8901 100644
--- a/src/engine/machina/SMFDriver.hpp
+++ b/src/engine/machina/SMFDriver.hpp
@@ -39,17 +39,17 @@ public:
 	SMFDriver(SharedPtr<Machine> machine = SharedPtr<Machine>());
 
 	SharedPtr<Machine> learn(const std::string& filename,
-	                         double             q=0.0,
-	                         Raul::BeatTime     max_duration=0);
+	                         Raul::TimeStamp    q,
+	                         Raul::TimeDuration max_duration);
 
 	SharedPtr<Machine> learn(const std::string& filename,
 	                         unsigned           track,
-	                         double             q=0.0,
-	                         Raul::BeatTime     max_duration=0);
+	                         Raul::TimeStamp    q,
+	                         Raul::TimeDuration max_duration);
 
-	void run(SharedPtr<Machine> machine, Raul::BeatTime max_time);
+	void run(SharedPtr<Machine> machine, Raul::TimeStamp max_time);
 	
-	void write_event(Raul::BeatTime       time,
+	void write_event(Raul::TimeStamp      time,
 	                 size_t               ev_size,
 	                 const unsigned char* ev) throw (std::logic_error)
 	{ _writer->write_event(time, ev_size, ev); }
@@ -65,8 +65,8 @@ private:
 	void learn_track(SharedPtr<MachineBuilder> builder,
 	                 Raul::SMFReader&          reader,
 	                 unsigned                  track,
-	                 double                    q,
-	                 Raul::BeatTime            max_duration=0);
+	                 Raul::TimeStamp           q,
+	                 Raul::TimeDuration        max_duration);
 };
 
 
-- 
cgit v1.2.1