aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2013-01-14 07:39:55 +0000
committerDavid Robillard <d@drobilla.net>2013-01-14 07:39:55 +0000
commit0a02e807beea6104248cb6cf00ef6689c9231912 (patch)
treecb279fb1a1b801c48fa83a59fb56dde486b6dbfd
parent035a94ce6c9a32025f88441ef8aedaf887a40318 (diff)
downloadmachina-0a02e807beea6104248cb6cf00ef6689c9231912.tar.gz
machina-0a02e807beea6104248cb6cf00ef6689c9231912.tar.bz2
machina-0a02e807beea6104248cb6cf00ef6689c9231912.zip
Fix saving and loading machines.
git-svn-id: http://svn.drobilla.net/lad/trunk/machina@4984 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--src/engine/Action.cpp33
-rw-r--r--src/engine/Action.hpp2
-rw-r--r--src/engine/ActionFactory.cpp12
-rw-r--r--src/engine/ActionFactory.hpp4
-rw-r--r--src/engine/Edge.cpp20
-rw-r--r--src/engine/Edge.hpp4
-rw-r--r--src/engine/Engine.cpp21
-rw-r--r--src/engine/Loader.cpp189
-rw-r--r--src/engine/Machine.cpp12
-rw-r--r--src/engine/MidiAction.cpp75
-rw-r--r--src/engine/MidiAction.hpp4
-rw-r--r--src/engine/Node.cpp39
-rw-r--r--src/engine/Node.hpp2
-rw-r--r--src/engine/machina/Loader.hpp5
-rw-r--r--src/engine/machina/URIs.hpp17
-rw-r--r--src/engine/wscript1
-rw-r--r--src/gui/main.cpp60
17 files changed, 231 insertions, 269 deletions
diff --git a/src/engine/Action.cpp b/src/engine/Action.cpp
deleted file mode 100644
index 8671d34..0000000
--- a/src/engine/Action.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- 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/>.
-*/
-
-#include "sord/sordmm.hpp"
-
-#include "Action.hpp"
-
-namespace machina {
-
-void
-Action::write_state(Sord::Model& model)
-{
- using namespace Raul;
-
- model.add_statement(rdf_id(model.world()),
- Sord::Curie(model.world(), "rdf:type"),
- Sord::Curie(model.world(), "machina:Action"));
-}
-
-} // namespace machina
diff --git a/src/engine/Action.hpp b/src/engine/Action.hpp
index 0201380..79b7fca 100644
--- a/src/engine/Action.hpp
+++ b/src/engine/Action.hpp
@@ -37,7 +37,7 @@ struct Action
, public Stateful {
virtual void execute(MIDISink* sink, Raul::TimeStamp time) = 0;
- virtual void write_state(Sord::Model& model);
+ virtual void write_state(Sord::Model& model) {}
};
class PrintAction : public Action
diff --git a/src/engine/ActionFactory.cpp b/src/engine/ActionFactory.cpp
index 37e5fff..f031149 100644
--- a/src/engine/ActionFactory.cpp
+++ b/src/engine/ActionFactory.cpp
@@ -31,23 +31,23 @@ ActionFactory::copy(SPtr<Action> copy)
}
SPtr<Action>
-ActionFactory::note_on(unsigned char note)
+ActionFactory::note_on(uint8_t note, uint8_t velocity)
{
- unsigned char buf[3];
+ uint8_t buf[3];
buf[0] = 0x90;
buf[1] = note;
- buf[2] = 0x40;
+ buf[2] = velocity;
return SPtr<Action>(new MidiAction(3, buf));
}
SPtr<Action>
-ActionFactory::note_off(unsigned char note)
+ActionFactory::note_off(uint8_t note, uint8_t velocity)
{
- unsigned char buf[3];
+ uint8_t buf[3];
buf[0] = 0x80;
buf[1] = note;
- buf[2] = 0x40;
+ buf[2] = velocity;
return SPtr<Action>(new MidiAction(3, buf));
}
diff --git a/src/engine/ActionFactory.hpp b/src/engine/ActionFactory.hpp
index c859aa7..db7aa68 100644
--- a/src/engine/ActionFactory.hpp
+++ b/src/engine/ActionFactory.hpp
@@ -25,8 +25,8 @@ struct Action;
namespace ActionFactory {
SPtr<Action> copy(SPtr<Action> copy);
-SPtr<Action> note_on(unsigned char note);
-SPtr<Action> note_off(unsigned char note);
+SPtr<Action> note_on(uint8_t note, uint8_t velocity=64);
+SPtr<Action> note_off(uint8_t note, uint8_t velocity=64);
}
} // namespace machina
diff --git a/src/engine/Edge.cpp b/src/engine/Edge.cpp
index 07ea2f6..cc76e61 100644
--- a/src/engine/Edge.cpp
+++ b/src/engine/Edge.cpp
@@ -39,11 +39,6 @@ Edge::write_state(Sord::Model& model)
const Sord::Node& rdf_id = this->rdf_id(model.world());
- model.add_statement(
- rdf_id,
- Sord::Curie(model.world(), "rdf:type"),
- Sord::Curie(model.world(), "machina:Edge"));
-
SPtr<Node> tail = _tail.lock();
SPtr<Node> head = _head;
@@ -54,20 +49,17 @@ Edge::write_state(Sord::Model& model)
&& head->rdf_id(model.world()).is_valid());
model.add_statement(rdf_id,
- Sord::Curie(model.world(), "machina:tail"),
+ Sord::URI(model.world(), MACHINA_NS_tail),
tail->rdf_id(model.world()));
model.add_statement(rdf_id,
- Sord::Curie(model.world(), "machina:head"),
+ Sord::URI(model.world(), MACHINA_NS_head),
head->rdf_id(model.world()));
- std::cerr << "FIXME: save atom" << std::endl;
- /*
- model.add_statement(
- rdf_id,
- Sord::Curie(model.world(), "machina:probability"),
- AtomRDF::atom_to_node(model, Atom(_probability.get())));
- */
+ model.add_statement(
+ rdf_id,
+ Sord::URI(model.world(), MACHINA_NS_probability),
+ Sord::Literal::decimal(model.world(), _probability.get(), 7));
}
} // namespace machina
diff --git a/src/engine/Edge.hpp b/src/engine/Edge.hpp
index 90511ca..db91ca7 100644
--- a/src/engine/Edge.hpp
+++ b/src/engine/Edge.hpp
@@ -35,8 +35,8 @@ class Edge
: public Stateful
{
public:
- Edge(WPtr<Node> tail, SPtr<Node> head)
- : _probability(1.0f)
+ Edge(WPtr<Node> tail, SPtr<Node> head, float probability=1.0f)
+ : _probability(probability)
, _tail(tail)
, _head(head)
{}
diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp
index c43d643..047abb9 100644
--- a/src/engine/Engine.cpp
+++ b/src/engine/Engine.cpp
@@ -62,15 +62,13 @@ Engine::new_driver(Raul::Forge& forge,
SPtr<Machine>
Engine::load_machine(const Glib::ustring& uri)
{
- SPtr<Machine> machine = _loader.load(uri);
- SPtr<Machine> old_machine;
+ SPtr<Machine> machine = _loader.load(uri);
+ SPtr<Machine> old_machine = _driver->machine(); // Keep reference
if (machine) {
- old_machine = _driver->machine(); // Keep a reference to old machine...
- _driver->set_machine(machine); // Switch driver to new machine
+ _driver->set_machine(machine); // Switch driver to new machine and wait
}
- // .. and drop it in this thread (to prevent deallocation in the RT thread)
-
+ // Drop (possibly last) reference to old_machine in this thread
return machine;
}
@@ -82,16 +80,13 @@ Engine::load_machine_midi(const Glib::ustring& uri,
double q,
Raul::TimeDuration dur)
{
- SPtr<SMFDriver> file_driver(new SMFDriver(_forge, dur.unit()));
- SPtr<Machine> machine = file_driver->learn(uri, q, dur);
- SPtr<Machine> old_machine;
+ SPtr<Machine> machine = _loader.load_midi(uri, q, dur);
+ SPtr<Machine> old_machine = _driver->machine(); // Keep reference
if (machine) {
- old_machine = _driver->machine(); // Keep a reference to old machine...
- _driver->set_machine(machine); // Switch driver to new machine
+ _driver->set_machine(machine); // Switch driver to new machine and wait
}
- // .. and drop it in this thread (to prevent deallocation in the RT thread)
-
+ // Drop (possibly last) reference to old_machine in this thread
return machine;
}
diff --git a/src/engine/Loader.cpp b/src/engine/Loader.cpp
index 64927e8..0497268 100644
--- a/src/engine/Loader.cpp
+++ b/src/engine/Loader.cpp
@@ -20,28 +20,59 @@
#include <glibmm/ustring.h>
+#include "lv2/lv2plug.in/ns/ext/midi/midi.h"
+
#include "machina/Loader.hpp"
+#include "machina/URIs.hpp"
#include "machina/Machine.hpp"
-#include "machina_config.h"
-#include "ActionFactory.hpp"
#include "Edge.hpp"
+#include "MidiAction.hpp"
#include "Node.hpp"
+#include "SMFDriver.hpp"
+#include "machina_config.h"
using namespace Raul;
using namespace std;
-#define NS_MACHINA "http://drobilla.net/ns/machina#"
-#define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-
namespace machina {
Loader::Loader(Raul::Forge& forge, Sord::World& rdf_world)
: _forge(forge)
, _rdf_world(rdf_world)
+{}
+
+static SPtr<Action>
+load_action(Sord::Model& model, Sord::Node node)
{
- _rdf_world.add_prefix("xsd", "http://www.w3.org/2001/XMLSchema#");
- _rdf_world.add_prefix("", "http://drobilla.net/ns/machina#");
+ if (!node.is_valid()) {
+ return SPtr<Action>();
+ }
+
+ Sord::URI rdf_type(model.world(), MACHINA_URI_RDF "type");
+ Sord::URI midi_NoteOn(model.world(), LV2_MIDI__NoteOn);
+ Sord::URI midi_NoteOff(model.world(), LV2_MIDI__NoteOff);
+ Sord::URI midi_noteNumber(model.world(), LV2_MIDI__noteNumber);
+ Sord::URI midi_velocity(model.world(), LV2_MIDI__velocity);
+
+ Sord::Node type = model.get(node, rdf_type, Sord::Node());
+ uint8_t status = 0;
+ if (type == midi_NoteOn) {
+ status = LV2_MIDI_MSG_NOTE_ON;
+ } else if (type == midi_NoteOff) {
+ status = LV2_MIDI_MSG_NOTE_OFF;
+ } else {
+ return SPtr<Action>();
+ }
+
+ Sord::Node num_node = model.get(node, midi_noteNumber, Sord::Node());
+ Sord::Node vel_node = model.get(node, midi_velocity, Sord::Node());
+
+ const uint8_t num = num_node.is_int() ? num_node.to_int() : 64;
+ const uint8_t vel = vel_node.is_int() ? vel_node.to_int() : 64;
+ const uint8_t event[3] = { status, num, vel };
+
+ return SPtr<Action>(new MidiAction(sizeof(event), event));
}
/** Load (create) all objects from RDF into the engine.
@@ -54,8 +85,6 @@ Loader::load(const Glib::ustring& uri)
{
using Glib::ustring;
- SPtr<Machine> machine;
-
ustring document_uri = uri;
// If "URI" doesn't contain a colon, try to resolve as a filename
@@ -63,105 +92,67 @@ Loader::load(const Glib::ustring& uri)
document_uri = "file://" + document_uri;
}
- const string machine_uri = string("<>");
+ cout << "Loading " << document_uri << endl;
- cout << "[Loader] Loading " << document_uri << endl;
+ TimeUnit beats(TimeUnit::BEATS, MACHINA_PPQN);
- machine = SPtr<Machine>(
- new Machine(TimeUnit::beats(MACHINA_PPQN)));
+ SPtr<Machine> machine(new Machine(beats));
typedef std::map<Sord::Node, SPtr<Node> > Created;
Created created;
+ Sord::URI base_uri(_rdf_world, document_uri);
Sord::Model model(_rdf_world, document_uri);
- SerdEnv* env = serd_env_new(NULL);
+
+ SerdEnv* env = serd_env_new(base_uri.to_serd_node());
model.load_file(env, SERD_TURTLE, document_uri);
serd_env_free(env);
Sord::Node nil;
- Sord::URI rdf_type(_rdf_world, NS_RDF "type");
- Sord::URI machina_SelectorNode(_rdf_world, NS_MACHINA "SelectorNode");
- Sord::URI machina_node(_rdf_world, NS_MACHINA "node");
- Sord::URI machina_initialNode(_rdf_world, NS_MACHINA "initialNode");
- Sord::URI machina_duration(_rdf_world, NS_MACHINA "duration");
- Sord::URI machina_edge(_rdf_world, NS_MACHINA "edge");
- Sord::URI machina_tail(_rdf_world, NS_MACHINA "tail");
- Sord::URI machina_head(_rdf_world, NS_MACHINA "head");
- Sord::URI machina_probability(_rdf_world, NS_MACHINA "probability");
-
- Sord::Node machine_node = Sord::URI(_rdf_world, ".");
-
- /* Get initial nodes */
- for (Sord::Iter i = model.find(machine_node, machina_initialNode, nil);
- !i.end(); ++i) {
- const Sord::Node& node_id = i.get_object();
- Sord::Iter d = model.find(node_id, machina_duration, nil);
- SPtr<Node> node(
- new Node(TimeStamp(TimeUnit(TimeUnit::BEATS, MACHINA_PPQN),
- d.get_object().to_float()),
- true));
-
- Sord::Iter s = model.find(node_id, rdf_type, machina_SelectorNode);
- if (!s.end()) {
- node->set_selector(true);
+ Sord::URI machina_SelectorNode(_rdf_world, MACHINA_NS_SelectorNode);
+ Sord::URI machina_duration(_rdf_world, MACHINA_NS_duration);
+ Sord::URI machina_edge(_rdf_world, MACHINA_NS_arc);
+ Sord::URI machina_head(_rdf_world, MACHINA_NS_head);
+ Sord::URI machina_node(_rdf_world, MACHINA_NS_node);
+ Sord::URI machina_onEnter(_rdf_world, MACHINA_NS_onEnter);
+ Sord::URI machina_onExit(_rdf_world, MACHINA_NS_onExit);
+ Sord::URI machina_probability(_rdf_world, MACHINA_NS_probability);
+ Sord::URI machina_start(_rdf_world, MACHINA_NS_start);
+ Sord::URI machina_tail(_rdf_world, MACHINA_NS_tail);
+ Sord::URI rdf_type(_rdf_world, MACHINA_URI_RDF "type");
+
+ Sord::Node subject = base_uri;
+
+ // Get start node ID (but re-use existing start node)
+ Sord::Iter i = model.find(subject, machina_start, nil);
+ if (i.end()) {
+ cerr << "error: Machine has no start node" << std::endl;
+ }
+ created[i.get_object()] = machine->initial_node();
+
+ // Get remaining nodes
+ for (Sord::Iter i = model.find(subject, machina_node, nil); !i.end(); ++i) {
+ const Sord::Node& id = i.get_object();
+ if (created.find(id) != created.end()) {
+ cerr << "warning: Machine lists the same node twice" << std::endl;
+ continue;
}
+ // Create node
+ Sord::Iter d = model.find(id, machina_duration, nil);
+ SPtr<Node> node(new Node(TimeStamp(beats, d.get_object().to_float())));
machine->add_node(node);
- created[node_id] = node;
- }
+ created[id] = node;
- /* Get remaining (non-initial) nodes */
- for (Sord::Iter i = model.find(machine_node, machina_node, nil);
- !i.end(); ++i) {
- const Sord::Node& node_id = i.get_object();
- Sord::Iter d = model.find(node_id, machina_duration, nil);
- if (created.find(node_id) == created.end()) {
- SPtr<Node> node(
- new Node(TimeStamp(TimeUnit(TimeUnit::BEATS, MACHINA_PPQN),
- d.get_object().to_float()),
- false));
- machine->add_node(node);
- created[node_id] = node;
- }
- }
-
-#if 0
- cerr << "FIXME: Load actions" << endl;
- /* Get note actions */
-
- query = Query(_rdf_world, ustring(
- "SELECT DISTINCT ?node ?note WHERE {\n"
- " ?node :enterAction [ a :MidiAction; :midiNote ?note ] ;\n"
- " :exitAction [ a :MidiAction; :midiNote ?note ] .\n"
- "}\n"));
-
- results = query.run(_rdf_world, model);
- for (; !results->finished(); results->next()) {
- Created::iterator node_i
- = created.find((const char*)results->get("node"));
- if (node_i != created.end()) {
- SPtr<Node> node = node_i->second;
- const int note_num = results->get("note").to_int();
- if (note_num >= 0 && note_num <= 127) {
- node->set_enter_action(
- ActionFactory::note_on((uint8_t)note_num));
- node->set_exit_action(
- ActionFactory::note_off((uint8_t)note_num));
- } else {
- cerr << "WARNING: MIDI note number out of range, ignoring."
- << endl;
- }
- } else {
- cerr << "WARNING: Found note for unknown states. Ignoring."
- << endl;
- }
+ node->set_enter_action(
+ load_action(model, model.get(id, machina_onEnter, nil)));
+ node->set_exit_action(
+ load_action(model, model.get(id, machina_onExit, nil)));
}
-#endif
- /* Get edges */
- for (Sord::Iter i = model.find(machine_node, machina_edge, nil);
- !i.end(); ++i) {
+ // Get arcs
+ for (Sord::Iter i = model.find(subject, machina_edge, nil); !i.end(); ++i) {
Sord::Node edge = i.get_object();
Sord::Iter t = model.find(edge, machina_tail, nil);
Sord::Iter h = model.find(edge, machina_head, nil);
@@ -179,16 +170,11 @@ Loader::load(const Glib::ustring& uri)
if (tail_i != created.end() && head_i != created.end()) {
const SPtr<Node> tail = tail_i->second;
const SPtr<Node> head = head_i->second;
-
- SPtr<Edge> edge(new Edge(tail, head));
- edge->set_probability(prob);
- tail->add_edge(edge);
-
+ tail->add_edge(SPtr<Edge>(new Edge(tail, head, prob)));
} else {
- cerr << "[Loader] WARNING: Ignored edge between unknown nodes "
+ cerr << "warning: Ignored edge between unknown nodes "
<< tail << " -> " << head << endl;
}
-
}
if (machine && !machine->nodes().empty()) {
@@ -199,4 +185,13 @@ Loader::load(const Glib::ustring& uri)
}
}
+SPtr<Machine>
+Loader::load_midi(const Glib::ustring& uri,
+ double q,
+ Raul::TimeDuration dur)
+{
+ SPtr<SMFDriver> file_driver(new SMFDriver(_forge, dur.unit()));
+ return file_driver->learn(uri, q, dur);
+}
+
} // namespace machina
diff --git a/src/engine/Machine.cpp b/src/engine/Machine.cpp
index b61e8d0..3cb85c1 100644
--- a/src/engine/Machine.cpp
+++ b/src/engine/Machine.cpp
@@ -352,22 +352,20 @@ Machine::write_state(Sord::Model& model)
{
using namespace Raul;
- model.world().add_prefix("machina", "http://drobilla.net/ns/machina#");
-
model.add_statement(model.base_uri(),
- Sord::Curie(model.world(), "rdf:type"),
- Sord::Curie(model.world(), "machina:Machine"));
+ Sord::URI(model.world(), MACHINA_URI_RDF "type"),
+ Sord::URI(model.world(), MACHINA_NS_Machine));
for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) {
(*n)->write_state(model);
if ((*n)->is_initial()) {
model.add_statement(model.base_uri(),
- Sord::Curie(model.world(), "machina:initialNode"),
+ Sord::URI(model.world(), MACHINA_NS_start),
(*n)->rdf_id(model.world()));
} else {
model.add_statement(model.base_uri(),
- Sord::Curie(model.world(), "machina:node"),
+ Sord::URI(model.world(), MACHINA_NS_node),
(*n)->rdf_id(model.world()));
}
}
@@ -379,7 +377,7 @@ Machine::write_state(Sord::Model& model)
(*e)->write_state(model);
model.add_statement(model.base_uri(),
- Sord::Curie(model.world(), "machina:edge"),
+ Sord::URI(model.world(), MACHINA_NS_arc),
(*e)->rdf_id(model.world()));
}
diff --git a/src/engine/MidiAction.cpp b/src/engine/MidiAction.cpp
index f1f1ccb..30de67a 100644
--- a/src/engine/MidiAction.cpp
+++ b/src/engine/MidiAction.cpp
@@ -14,11 +14,10 @@
along with Machina. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <iostream>
-
-#include "raul/Atom.hpp"
-
+#include "lv2/lv2plug.in/ns/ext/midi/midi.h"
+#include "machina/URIs.hpp"
#include "machina/types.hpp"
+#include "raul/Atom.hpp"
#include "MIDISink.hpp"
#include "MidiAction.hpp"
@@ -27,11 +26,8 @@ namespace machina {
/** Create a MIDI action.
*
- * Creating a NULL MIDIAction is okay, pass event=NULL and
- * the action will simply do nothing until a set_event (for MIDI learning).
- *
- * Memory management of @event is the caller's responsibility
- * (ownership is not taken).
+ * Creating a NULL MidiAction is okay, pass event=NULL and the action will
+ * simply do nothing until a set_event (for MIDI learning).
*/
MidiAction::MidiAction(size_t size,
const byte* event)
@@ -47,13 +43,6 @@ MidiAction::~MidiAction()
delete[] _event.load();
}
-/** Set the MIDI event to be emitted when the action executes.
- *
- * Returns pointer to old event (caller's responsibility to free if non-NULL).
- * Safe to call concurrently with execute.
- *
- * Returns true on success.
- */
bool
MidiAction::set_event(size_t size, const byte* new_event)
{
@@ -71,42 +60,44 @@ MidiAction::set_event(size_t size, const byte* new_event)
}
}
-/** Execute the action.
- *
- * Safe to call concurrently with set_event.
- */
void
MidiAction::execute(MIDISink* sink, Raul::TimeStamp time)
{
- const byte* const event = _event.load();
-
- if (event) {
- if (sink) {
- sink->write_event(time, _size, event);
- }
- } else {
- std::cerr << "NULL MIDI ACTION";
+ const byte* const ev = _event.load();
+ if (ev && sink) {
+ sink->write_event(time, _size, ev);
}
}
void
MidiAction::write_state(Sord::Model& model)
{
- using namespace Raul;
-
- Action::write_state(model);
-
- model.add_statement(rdf_id(model.world()),
- Sord::Curie(model.world(), "rdf:type"),
- Sord::Curie(model.world(), "machina:MidiAction"));
+ const uint8_t* ev = event();
+ const uint8_t type = (ev[0] & 0xF0);
+ if (type == LV2_MIDI_MSG_NOTE_ON) {
+ model.add_statement(
+ rdf_id(model.world()),
+ Sord::URI(model.world(), MACHINA_URI_RDF "type"),
+ Sord::URI(model.world(), LV2_MIDI__NoteOn));
+ } else if (type == LV2_MIDI_MSG_NOTE_OFF) {
+ model.add_statement(
+ rdf_id(model.world()),
+ Sord::URI(model.world(), MACHINA_URI_RDF "type"),
+ Sord::URI(model.world(), LV2_MIDI__NoteOff));
+ } else {
+ std::cerr << "warning: Unable to serialise MIDI event" << std::endl;
+ }
- // FIXME: Assumes note on/note off
- std::cerr << "FIXME: AtomRDF" << std::endl;
- /*
- model.add_statement(rdf_id(model.world()),
- Sord::Curie(model.world(), "machina:midiNote"),
- AtomRDF::atom_to_node(model, Atom((int)(_event.get()[1]))));
- */
+ model.add_statement(
+ rdf_id(model.world()),
+ Sord::URI(model.world(), LV2_MIDI__noteNumber),
+ Sord::Literal::integer(model.world(), (int)ev[1]));
+ if (ev[2] != 64) {
+ model.add_statement(
+ rdf_id(model.world()),
+ Sord::URI(model.world(), LV2_MIDI__velocity),
+ Sord::Literal::integer(model.world(), (int)ev[2]));
+ }
}
} // namespace machina
diff --git a/src/engine/MidiAction.hpp b/src/engine/MidiAction.hpp
index 66ab962..64a2c65 100644
--- a/src/engine/MidiAction.hpp
+++ b/src/engine/MidiAction.hpp
@@ -29,8 +29,7 @@ namespace machina {
class MIDISink;
-class MidiAction
- : public Action
+class MidiAction : public Action
{
public:
~MidiAction();
@@ -48,7 +47,6 @@ public:
virtual void write_state(Sord::Model& model);
private:
-
size_t _size;
const size_t _max_size;
std::atomic<byte*> _event;
diff --git a/src/engine/Node.cpp b/src/engine/Node.cpp
index 3d13df4..8ee92e7 100644
--- a/src/engine/Node.cpp
+++ b/src/engine/Node.cpp
@@ -70,7 +70,7 @@ Node::random_edge()
// FIXME: O(n) worst case :(
for (Edges::const_iterator e = _edges.begin(); e != _edges.end(); ++e,
- --i) {
+ --i) {
if (i == 0) {
ret = *e;
break;
@@ -222,36 +222,31 @@ Node::write_state(Sord::Model& model)
if (_is_selector)
model.add_statement(
- rdf_id,
- Sord::Curie(model.world(), "rdf:type"),
- Sord::Curie(model.world(), "machina:SelectorNode"));
+ rdf_id,
+ Sord::URI(model.world(), MACHINA_URI_RDF "type"),
+ Sord::URI(model.world(), MACHINA_NS_SelectorNode));
else
model.add_statement(
- rdf_id,
- Sord::Curie(model.world(), "rdf:type"),
- Sord::Curie(model.world(), "machina:Node"));
-
- std::cerr << "ATOMRDF" << std::endl;
- /*
- model.add_statement(
- rdf_id,
- Sord::Curie(model.world(), "machina:duration"),
- AtomRDF::atom_to_node(model, Atom((float)_duration.to_double())));
- */
+ rdf_id,
+ Sord::URI(model.world(), MACHINA_URI_RDF "type"),
+ Sord::URI(model.world(), MACHINA_NS_Node));
- if (_enter_action) {
- _enter_action->write_state(model);
+ model.add_statement(
+ rdf_id,
+ Sord::URI(model.world(), MACHINA_NS_duration),
+ Sord::Literal::decimal(model.world(), _duration.to_double(), 7));
- model.add_statement(rdf_id,
- Sord::Curie(model.world(), "machina:enterAction"),
- _enter_action->rdf_id(model.world()));
+ if (_enter_action) {
+ _enter_action->write_state(model);
+ model.add_statement(rdf_id,
+ Sord::URI(model.world(), MACHINA_NS_onEnter),
+ _enter_action->rdf_id(model.world()));
}
if (_exit_action) {
_exit_action->write_state(model);
-
model.add_statement(rdf_id,
- Sord::Curie(model.world(), "machina:exitAction"),
+ Sord::URI(model.world(), MACHINA_NS_onExit),
_exit_action->rdf_id(model.world()));
}
}
diff --git a/src/engine/Node.hpp b/src/engine/Node.hpp
index 807c506..3b22d81 100644
--- a/src/engine/Node.hpp
+++ b/src/engine/Node.hpp
@@ -44,7 +44,7 @@ using Raul::TimeUnit;
class Node : public Stateful
{
public:
- Node(TimeDuration duration, bool initial = false);
+ Node(TimeDuration duration, bool initial=false);
Node(const Node& copy);
void set_enter_action(SPtr<Action> action);
diff --git a/src/engine/machina/Loader.hpp b/src/engine/machina/Loader.hpp
index 99f1577..548e23a 100644
--- a/src/engine/machina/Loader.hpp
+++ b/src/engine/machina/Loader.hpp
@@ -21,6 +21,7 @@
#include "machina/types.hpp"
#include "raul/Atom.hpp"
+#include "raul/TimeStamp.hpp"
#include "sord/sordmm.hpp"
using Sord::Namespaces;
@@ -36,6 +37,10 @@ public:
SPtr<Machine> load(const Glib::ustring& filename);
+ SPtr<Machine> load_midi(const Glib::ustring& filename,
+ double q,
+ Raul::TimeDuration dur);
+
private:
Raul::Forge& _forge;
Sord::World& _rdf_world;
diff --git a/src/engine/machina/URIs.hpp b/src/engine/machina/URIs.hpp
index 105291a..eba1692 100644
--- a/src/engine/machina/URIs.hpp
+++ b/src/engine/machina/URIs.hpp
@@ -23,6 +23,23 @@
#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
diff --git a/src/engine/wscript b/src/engine/wscript
index 60bddd3..902ffd0 100644
--- a/src/engine/wscript
+++ b/src/engine/wscript
@@ -3,7 +3,6 @@ from waflib.extras import autowaf as autowaf
def build(bld):
core_source = '''
- Action.cpp
ActionFactory.cpp
Controller.cpp
Edge.cpp
diff --git a/src/gui/main.cpp b/src/gui/main.cpp
index 46cb21c..04d9e6d 100644
--- a/src/gui/main.cpp
+++ b/src/gui/main.cpp
@@ -14,15 +14,19 @@
along with Machina. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "machina_config.h"
#include <signal.h>
+
#include <iostream>
#include <string>
-#include "sord/sordmm.hpp"
+
+#include "lv2/lv2plug.in/ns/ext/midi/midi.h"
#include "machina/Engine.hpp"
#include "machina/Loader.hpp"
#include "machina/Machine.hpp"
#include "machina/URIs.hpp"
+#include "machina_config.h"
+#include "sord/sordmm.hpp"
+
#include "MachinaGUI.hpp"
using namespace std;
@@ -31,49 +35,55 @@ using namespace machina;
int
main(int argc, char** argv)
{
- if (!Glib::thread_supported()) {
- Glib::thread_init();
- }
+ Glib::thread_init();
+ machina::URIs::init();
Sord::World rdf_world;
+ rdf_world.add_prefix("", MACHINA_NS);
+ rdf_world.add_prefix("midi", LV2_MIDI_PREFIX);
- machina::URIs::init();
-
+ Raul::Forge forge;
SPtr<machina::Machine> machine;
+ Raul::TimeUnit beats(TimeUnit::BEATS, MACHINA_PPQN);
+
// Load machine, if given
-#if 0
if (argc >= 2) {
const string filename = argv[1];
- cout << "Building machine from MIDI file " << filename << endl;
- SPtr<machina::SMFDriver> file_driver(new machina::SMFDriver());
-
- if (argc >= 3) {
- float q = strtof(argv[2], NULL);
- cout << "Quantization: " << q << endl;
- machine = file_driver->learn(filename, q);
- } else {
- cout << "No quantization." << endl;
- machine = file_driver->learn(filename);
+ const string ext = filename.substr(filename.length() - 4);
+
+ if (ext == ".ttl") {
+ cout << "Loading machine from " << filename << endl;
+ machine = Loader(forge, rdf_world).load(filename);
+
+ } else if (ext == ".mid") {
+ cout << "Building machine from MIDI file " << filename << endl;
+
+ double q = 0.0;
+ if (argc >= 3) {
+ q = strtod(argv[2], NULL);
+ cout << "Quantization: " << q << endl;
+ }
+
+ machine = Loader(forge, rdf_world).load_midi(
+ filename, q, Raul::TimeDuration(beats, 0, 0));
}
if (!machine) {
- cout << "Not MIDI, attempting to load machine" << endl;
- machine = Loader(rdf_world).load(filename);
+ cerr << "Failed to load machine, exiting" << std::endl;
+ return 1;
}
}
-#endif
- Raul::Forge forge;
if (!machine) {
- machine = SPtr<Machine>(new Machine(TimeUnit(TimeUnit::BEATS, 19200)));
+ machine = SPtr<Machine>(new Machine(beats));
}
std::string driver_name = "smf";
- #ifdef HAVE_JACK
+#ifdef HAVE_JACK
driver_name = "jack";
- #endif
+#endif
// Build engine
SPtr<Driver> driver(Engine::new_driver(forge, driver_name, machine));