aboutsummaryrefslogtreecommitdiffstats
path: root/src/engine/Loader.cpp
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 /src/engine/Loader.cpp
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
Diffstat (limited to 'src/engine/Loader.cpp')
-rw-r--r--src/engine/Loader.cpp189
1 files changed, 92 insertions, 97 deletions
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