aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/engine/Engine.cpp24
-rw-r--r--src/engine/JackDriver.cpp13
-rw-r--r--src/engine/Loader.cpp7
-rw-r--r--src/engine/MachineBuilder.cpp24
-rw-r--r--src/engine/machina/Driver.hpp3
-rw-r--r--src/engine/machina/Engine.hpp1
-rw-r--r--src/engine/machina/JackDriver.hpp2
-rw-r--r--src/gui/EdgeView.cpp21
-rw-r--r--src/gui/EdgeView.hpp3
-rw-r--r--src/gui/MachinaGUI.cpp24
-rw-r--r--src/gui/MachinaGUI.hpp4
-rw-r--r--src/gui/NodePropertiesWindow.cpp19
-rw-r--r--src/gui/NodePropertiesWindow.hpp4
-rw-r--r--src/gui/machina.glade33
-rw-r--r--src/gui/main.cpp5
-rwxr-xr-xutil/machina2dot107
16 files changed, 256 insertions, 38 deletions
diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp
index 5da3289..69402a3 100644
--- a/src/engine/Engine.cpp
+++ b/src/engine/Engine.cpp
@@ -36,6 +36,7 @@ Engine::load_machine(const Glib::ustring& uri)
if (m) {
m->activate();
_driver->set_machine(m);
+ //_driver->machine()->nodes().append(m->nodes());
}
// .. and drop it in this thread (to prevent deallocation in the RT thread)
@@ -44,6 +45,26 @@ Engine::load_machine(const Glib::ustring& uri)
}
+/** Load the machine at @a uri, and insert it into the current machine..
+ * Safe to call while engine is processing.
+ */
+SharedPtr<Machine>
+Engine::import_machine(const Glib::ustring& uri)
+{
+ SharedPtr<Machine> old_machine = _driver->machine(); // Hold a reference to current machine..
+
+ SharedPtr<Machine> m = Loader().load(uri);
+ if (m) {
+ m->activate();
+ _driver->machine()->nodes().append(m->nodes());
+ }
+
+ // .. and drop it in this thread (to prevent deallocation in the RT thread)
+
+ return _driver->machine();
+}
+
+
/** Learn the SMF (MIDI) file at @a uri, and run the resulting machine
* (replacing current machine).
* Safe to call while engine is processing.
@@ -56,7 +77,8 @@ Engine::learn_midi(const Glib::ustring& uri)
SharedPtr<SMFDriver> file_driver(new SMFDriver());
SharedPtr<Machine> m = file_driver->learn(uri, 32.0); // FIXME: hardcoded
m->activate();
- _driver->set_machine(m);
+ //_driver->set_machine(m);
+ _driver->machine()->nodes().append(m->nodes());
// .. and drop it in this thread (to prevent deallocation in the RT thread)
diff --git a/src/engine/JackDriver.cpp b/src/engine/JackDriver.cpp
index 7df3a4b..3493105 100644
--- a/src/engine/JackDriver.cpp
+++ b/src/engine/JackDriver.cpp
@@ -295,6 +295,16 @@ JackDriver::on_process(jack_nframes_t nframes)
void
+JackDriver::reset()
+{
+ // FIXME: Flag audio thread and end active notes, etc
+ _machine->deactivate();
+ _machine->reset();
+ _cycle_time.set_start(0);
+}
+
+
+void
JackDriver::start_record()
{
std::cerr << "START RECORD" << std::endl;
@@ -314,7 +324,8 @@ JackDriver::finish_record()
std::cout << "Learned machine! " << machine->nodes().size() << " nodes." << std::endl;
_recorder.reset();
machine->activate();
- set_machine(machine);
+ //set_machine(machine);
+ _machine->nodes().append(machine->nodes());
}
diff --git a/src/engine/Loader.cpp b/src/engine/Loader.cpp
index 539c86f..b3e4c81 100644
--- a/src/engine/Loader.cpp
+++ b/src/engine/Loader.cpp
@@ -137,6 +137,11 @@ Loader::load(const Glib::ustring& uri)
}
+ for (Created::iterator n = created.begin(); n != created.end(); ++n) {
+ cout << "NODE: " << n->first << endl;
+ }
+
+
/* Get note actions */
query = Raul::RDFQuery(*_namespaces, Glib::ustring(
@@ -152,6 +157,8 @@ Loader::load(const Glib::ustring& uri)
const Glib::ustring& node_id = (*i)["node"];
const Glib::ustring& note = (*i)["note"];
+ cerr << "NOTE: " << node_id << " = " << note << endl;
+
Created::iterator node_i = created.find(node_id);
if (node_i != created.end()) {
SharedPtr<Node> node = node_i->second;
diff --git a/src/engine/MachineBuilder.cpp b/src/engine/MachineBuilder.cpp
index 515f1a0..c8ad273 100644
--- a/src/engine/MachineBuilder.cpp
+++ b/src/engine/MachineBuilder.cpp
@@ -73,22 +73,22 @@ MachineBuilder::connect_nodes(SharedPtr<Machine> m,
SharedPtr<Node> delay_node;
- cerr << "******" << endl;
+ /*cerr << "******" << endl;
cerr << "Connect nodes durations: " << tail->duration() << " .. " << head->duration() << endl;
- cerr << "Connect nodes times: " << tail_end_time << " .. " << head_start_time << endl;
+ cerr << "Connect nodes times: " << tail_end_time << " .. " << head_start_time << endl;*/
if (is_delay_node(tail) && tail->outgoing_edges().size() == 0) {
// Tail is a delay node, just accumulate the time difference into it
- cerr << "Accumulating delay " << tail_end_time << " .. " << head_start_time << endl;
+ //cerr << "Accumulating delay " << tail_end_time << " .. " << head_start_time << endl;
tail->set_duration(tail->duration() + head_start_time - tail_end_time);
tail->add_outgoing_edge(SharedPtr<Edge>(new Edge(tail, head)));
} else if (head_start_time == tail_end_time) {
// Connect directly
- cerr << "Connnecting directly " << tail_end_time << " .. " << head_start_time << endl;
+ //cerr << "Connnecting directly " << tail_end_time << " .. " << head_start_time << endl;
tail->add_outgoing_edge(SharedPtr<Edge>(new Edge(tail, head)));
} else {
// Need to actually create a delay node
- cerr << "Adding delay node for " << tail_end_time << " .. " << head_start_time << endl;
+ //cerr << "Adding delay node for " << tail_end_time << " .. " << head_start_time << endl;
delay_node = SharedPtr<Node>(new Node());
delay_node->set_duration(head_start_time - tail_end_time);
tail->add_outgoing_edge(SharedPtr<Edge>(new Edge(tail, delay_node)));
@@ -96,7 +96,7 @@ MachineBuilder::connect_nodes(SharedPtr<Machine> m,
m->add_node(delay_node);
}
- cerr << "******" << endl << endl;
+ /*cerr << "******" << endl << endl;*/
return delay_node;
}
@@ -109,7 +109,7 @@ MachineBuilder::event(Raul::BeatTime time_offset,
{
Raul::BeatTime t = _time + time_offset;
- cerr << "t = " << t << endl;
+ //cerr << "t = " << t << endl;
if (ev_size > 0) {
if ((buf[0] & 0xF0) == MIDI_CMD_NOTE_ON) {
@@ -150,6 +150,8 @@ MachineBuilder::event(Raul::BeatTime time_offset,
resolved->set_duration(t - resolved->enter_time());
if (_active_nodes.size() == 1) {
+
+ //cerr << "{ RESOLVING, t= " << t << "\n";
_connect_node_end_time = t;
@@ -176,7 +178,7 @@ MachineBuilder::event(Raul::BeatTime time_offset,
if (is_delay_node(_connect_node) && _connect_node->duration() == 0
&& _connect_node->outgoing_edges().size() == 1
&& (*_connect_node->outgoing_edges().begin())->head() == resolved) {
- cerr << "TRIMMING\n";
+ //cerr << "TRIMMING\n";
_connect_node->outgoing_edges().clear();
assert(_connect_node->outgoing_edges().empty());
_connect_node->set_enter_action(resolved->enter_action());
@@ -188,12 +190,16 @@ MachineBuilder::event(Raul::BeatTime time_offset,
if (_machine->nodes().find(_connect_node) == _machine->nodes().end())
_machine->add_node(_connect_node);
} else {
+ //cerr << "RESOLVED\n";
_connect_node = resolved;
_machine->add_node(resolved);
}
}
+ //cerr << "}";
+
} else {
+ //cerr << "ADDING POLY\n";
_poly_nodes.push_back(make_pair(resolved->enter_time(), resolved));
}
@@ -217,7 +223,7 @@ MachineBuilder::resolve()
{
if ( ! _active_nodes.empty()) {
for (list<SharedPtr<Node> >::iterator i = _active_nodes.begin(); i != _active_nodes.end(); ++i) {
- cerr << "WARNING: Resolving stuck note from MIDI file." << endl;
+ cerr << "WARNING: Resolving stuck note." << endl;
SharedPtr<MidiAction> action = PtrCast<MidiAction>((*i)->enter_action());
if (!action)
continue;
diff --git a/src/engine/machina/Driver.hpp b/src/engine/machina/Driver.hpp
index bf4d2be..acc4278 100644
--- a/src/engine/machina/Driver.hpp
+++ b/src/engine/machina/Driver.hpp
@@ -1,4 +1,5 @@
/* This file is part of Machina.
+ * _engine->driver()->reset_time();
* Copyright (C) 2007 Dave Robillard <http://drobilla.net>
*
* Machina is free software; you can redistribute it and/or modify it under the
@@ -39,6 +40,8 @@ public:
virtual void activate() {}
virtual void deactivate() {}
+ virtual void reset() {}
+
virtual bool recording() { return false; }
virtual void start_record() {}
virtual void finish_record() {}
diff --git a/src/engine/machina/Engine.hpp b/src/engine/machina/Engine.hpp
index 82c21ba..dc47b2a 100644
--- a/src/engine/machina/Engine.hpp
+++ b/src/engine/machina/Engine.hpp
@@ -37,6 +37,7 @@ public:
SharedPtr<Machine> machine() { return _driver->machine(); }
SharedPtr<Machine> load_machine(const Glib::ustring& uri);
+ SharedPtr<Machine> import_machine(const Glib::ustring& uri);
SharedPtr<Machine> learn_midi(const Glib::ustring& uri);
void set_bpm(double bpm);
diff --git a/src/engine/machina/JackDriver.hpp b/src/engine/machina/JackDriver.hpp
index 47b718d..1ab6643 100644
--- a/src/engine/machina/JackDriver.hpp
+++ b/src/engine/machina/JackDriver.hpp
@@ -62,6 +62,8 @@ public:
void set_bpm(double bpm) { _bpm.set(bpm); }
void set_quantization(double quantization) { _quantization.set(quantization); }
+ void reset();
+
bool recording() { return _recording.get(); }
void start_record();
void finish_record();
diff --git a/src/gui/EdgeView.cpp b/src/gui/EdgeView.cpp
index fccf8d5..d8e11a9 100644
--- a/src/gui/EdgeView.cpp
+++ b/src/gui/EdgeView.cpp
@@ -42,11 +42,26 @@ EdgeView::length_hint() const
void
+EdgeView::show_label(bool show)
+{
+ if (show) {
+ char label[4];
+ snprintf(label, 4, "%3f", _edge->probability());
+ set_label(label);
+ } else {
+ set_label("");
+ }
+}
+
+
+void
EdgeView::update_label()
{
- char label[4];
- snprintf(label, 4, "%3f", _edge->probability());
- set_label(label);
+ if (_label) {
+ char label[4];
+ snprintf(label, 4, "%3f", _edge->probability());
+ set_label(label);
+ }
}
diff --git a/src/gui/EdgeView.hpp b/src/gui/EdgeView.hpp
index c394d49..61de52f 100644
--- a/src/gui/EdgeView.hpp
+++ b/src/gui/EdgeView.hpp
@@ -33,11 +33,12 @@ public:
SharedPtr<Machina::Edge> edge() { return _edge; }
- void update_label();
+ void show_label(bool show);
virtual double length_hint() const;
private:
+ void update_label();
bool on_event(GdkEvent* ev);
SharedPtr<Machina::Edge> _edge;
diff --git a/src/gui/MachinaGUI.cpp b/src/gui/MachinaGUI.cpp
index 3ddb13f..4098ff8 100644
--- a/src/gui/MachinaGUI.cpp
+++ b/src/gui/MachinaGUI.cpp
@@ -29,6 +29,7 @@
#include "MachinaGUI.hpp"
#include "MachinaCanvas.hpp"
#include "NodeView.hpp"
+#include "EdgeView.hpp"
MachinaGUI::MachinaGUI(SharedPtr<Machina::Engine> engine)
@@ -58,6 +59,7 @@ MachinaGUI::MachinaGUI(SharedPtr<Machina::Engine> engine)
xml->get_widget("export_midi_menuitem", _menu_export_midi);
xml->get_widget("export_graphviz_menuitem", _menu_export_graphviz);
xml->get_widget("view_toolbar_menuitem", _menu_view_toolbar);
+ xml->get_widget("view_labels_menuitem", _menu_view_labels);
//xml->get_widget("view_refresh_menuitem", _menu_view_refresh);
//xml->get_widget("view_messages_menuitem", _menu_view_messages);
xml->get_widget("help_about_menuitem", _menu_help_about);
@@ -115,6 +117,8 @@ MachinaGUI::MachinaGUI(SharedPtr<Machina::Engine> engine)
// sigc::mem_fun(this, &MachinaGUI::menu_view_refresh));
_menu_view_toolbar->signal_toggled().connect(
sigc::mem_fun(this, &MachinaGUI::show_toolbar_toggled));
+ _menu_view_labels->signal_toggled().connect(
+ sigc::mem_fun(this, &MachinaGUI::show_labels_toggled));
//_menu_view_messages->signal_toggled().connect(
// sigc::mem_fun(this, &MachinaGUI::show_messages_toggled));
_menu_help_about->signal_activate().connect(
@@ -346,7 +350,8 @@ MachinaGUI::menu_file_open()
const int result = dialog.run();
if (result == Gtk::RESPONSE_OK) {
- SharedPtr<Machina::Machine> new_machine = _engine->load_machine(dialog.get_uri());
+ //SharedPtr<Machina::Machine> new_machine = _engine->load_machine(dialog.get_uri());
+ SharedPtr<Machina::Machine> new_machine = _engine->import_machine(dialog.get_uri());
if (new_machine) {
_canvas->destroy();
_canvas->build(new_machine);
@@ -596,6 +601,21 @@ MachinaGUI::show_toolbar_toggled()
_toolbar->hide();
}
+
+void
+MachinaGUI::show_labels_toggled()
+{
+ const bool show = _menu_view_labels->get_active();
+
+ for (ConnectionList::iterator c = _canvas->connections().begin();
+ c != _canvas->connections().end(); ++c) {
+ const SharedPtr<EdgeView> ev = PtrCast<EdgeView>(*c);
+ if (ev)
+ ev->show_label(show);
+ }
+}
+
+
/*
void
MachinaGUI::menu_view_refresh()
@@ -643,7 +663,7 @@ MachinaGUI::stop_clicked()
_engine->driver()->finish_record();
} else {
_engine->machine()->deactivate();
- _engine->machine()->reset();
+ _engine->driver()->reset();
}
update_toolbar();
diff --git a/src/gui/MachinaGUI.hpp b/src/gui/MachinaGUI.hpp
index 96fb772..eba8a93 100644
--- a/src/gui/MachinaGUI.hpp
+++ b/src/gui/MachinaGUI.hpp
@@ -64,6 +64,7 @@ protected:
void menu_export_graphviz();
//void show_messages_toggled();
void show_toolbar_toggled();
+ void show_labels_toggled();
//void menu_view_refresh();
void menu_help_about();
void menu_help_help();
@@ -110,9 +111,10 @@ protected:
Gtk::MenuItem* _menu_export_midi;
Gtk::MenuItem* _menu_export_graphviz;
Gtk::MenuItem* _menu_help_about;
+ Gtk::CheckMenuItem* _menu_view_labels;
Gtk::CheckMenuItem* _menu_view_toolbar;
//Gtk::CheckMenuItem* _menu_view_messages;
- Gtk::MenuItem* _menu_view_refresh;
+ //Gtk::MenuItem* _menu_view_refresh;
Gtk::MenuItem* _menu_help_help;
Gtk::ScrolledWindow* _canvas_scrolledwindow;
Gtk::TextView* _status_text;
diff --git a/src/gui/NodePropertiesWindow.cpp b/src/gui/NodePropertiesWindow.cpp
index 151c602..6ba3e47 100644
--- a/src/gui/NodePropertiesWindow.cpp
+++ b/src/gui/NodePropertiesWindow.cpp
@@ -34,11 +34,13 @@ NodePropertiesWindow::NodePropertiesWindow(BaseObjectType* cobject, const Glib::
xml->get_widget("node_properties_note_spinbutton", _note_spinbutton);
xml->get_widget("node_properties_duration_spinbutton", _duration_spinbutton);
+ xml->get_widget("node_properties_apply_button", _apply_button);
xml->get_widget("node_properties_cancel_button", _cancel_button);
xml->get_widget("node_properties_ok_button", _ok_button);
- _ok_button->signal_clicked().connect(sigc::mem_fun(this, &NodePropertiesWindow::ok_clicked));
+ _apply_button->signal_clicked().connect(sigc::mem_fun(this, &NodePropertiesWindow::apply_clicked));
_cancel_button->signal_clicked().connect(sigc::mem_fun(this, &NodePropertiesWindow::cancel_clicked));
+ _ok_button->signal_clicked().connect(sigc::mem_fun(this, &NodePropertiesWindow::ok_clicked));
}
@@ -48,11 +50,10 @@ NodePropertiesWindow::~NodePropertiesWindow()
void
-NodePropertiesWindow::ok_clicked()
+NodePropertiesWindow::apply_clicked()
{
- assert(this == _instance);
- delete _instance;
- _instance = NULL;
+ double duration = _duration_spinbutton->get_value();
+ _node->set_duration(duration);
}
@@ -64,6 +65,14 @@ NodePropertiesWindow::cancel_clicked()
_instance = NULL;
}
+
+void
+NodePropertiesWindow::ok_clicked()
+{
+ apply_clicked();
+ cancel_clicked();
+}
+
void
NodePropertiesWindow::set_node(SharedPtr<Machina::Node> node)
diff --git a/src/gui/NodePropertiesWindow.hpp b/src/gui/NodePropertiesWindow.hpp
index 461b51b..51ab42b 100644
--- a/src/gui/NodePropertiesWindow.hpp
+++ b/src/gui/NodePropertiesWindow.hpp
@@ -34,8 +34,9 @@ private:
void set_node(SharedPtr<Machina::Node> node);
- void ok_clicked();
+ void apply_clicked();
void cancel_clicked();
+ void ok_clicked();
static NodePropertiesWindow* _instance;
@@ -43,6 +44,7 @@ private:
Gtk::SpinButton* _note_spinbutton;
Gtk::SpinButton* _duration_spinbutton;
+ Gtk::Button* _apply_button;
Gtk::Button* _cancel_button;
Gtk::Button* _ok_button;
};
diff --git a/src/gui/machina.glade b/src/gui/machina.glade
index fb61bd8..b5349be 100644
--- a/src/gui/machina.glade
+++ b/src/gui/machina.glade
@@ -46,6 +46,7 @@
<child>
<widget class="GtkImageMenuItem" id="open_menuitem">
<property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Open a saved machine</property>
<property name="label">gtk-open</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_open_session_menuitem_activate" last_modification_time="Sun, 01 Oct 2006 07:00:37 GMT"/>
@@ -55,6 +56,7 @@
<child>
<widget class="GtkImageMenuItem" id="save_menuitem">
<property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Save machine</property>
<property name="label">gtk-save</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_save_session_menuitem_activate" last_modification_time="Sun, 01 Oct 2006 07:01:40 GMT"/>
@@ -64,6 +66,7 @@
<child>
<widget class="GtkImageMenuItem" id="save_as_menuitem">
<property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Save machine to file</property>
<property name="label">gtk-save-as</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_save_session_as_menuitem_activate" last_modification_time="Sun, 01 Oct 2006 07:01:40 GMT"/>
@@ -79,6 +82,7 @@
<child>
<widget class="GtkImageMenuItem" id="import_midi_menuitem">
<property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Import a MIDI file</property>
<property name="label" translatable="yes">_Import MIDI...</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_learn_midi_menuitem_activate" last_modification_time="Fri, 02 Mar 2007 21:00:16 GMT"/>
@@ -101,6 +105,7 @@
<child>
<widget class="GtkImageMenuItem" id="export_midi_menuitem">
<property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Export a MIDI file</property>
<property name="label" translatable="yes">_Export MIDI...</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_export_midi_menuitem_activate" last_modification_time="Fri, 02 Mar 2007 20:59:46 GMT"/>
@@ -129,7 +134,7 @@
<child>
<widget class="GtkImageMenuItem" id="export_graphviz_menuitem">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Export a DOT file for rendering diagram with the GraphViz suite of tools</property>
+ <property name="tooltip" translatable="yes">Export a DOT file for rendering with GraphViz</property>
<property name="label" translatable="yes">Export _GraphViz...</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_export_graphviz_menuitem_activate" last_modification_time="Mon, 12 Mar 2007 19:47:58 GMT"/>
@@ -158,6 +163,7 @@
<child>
<widget class="GtkImageMenuItem" id="quit_menuitem">
<property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Exit Machina</property>
<property name="label">gtk-quit</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_quit1_activate" last_modification_time="Sat, 11 Sep 2004 20:05:11 GMT"/>
@@ -836,12 +842,12 @@ Connect some nodes up and double click one. You'll get it.</property>
<widget class="GtkDialog" id="node_properties_dialog">
<property name="border_width">8</property>
- <property name="title" translatable="yes">Node Properties</property>
+ <property name="title" translatable="yes">dialog1</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">False</property>
- <property name="destroy_with_parent">True</property>
+ <property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">True</property>
<property name="skip_pager_hint">True</property>
@@ -852,17 +858,30 @@ Connect some nodes up and double click one. You'll get it.</property>
<property name="has_separator">True</property>
<child internal-child="vbox">
- <widget class="GtkVBox" id="dialog-vbox2">
+ <widget class="GtkVBox" id="dialog-vbox3">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">8</property>
<child internal-child="action_area">
- <widget class="GtkHButtonBox" id="dialog-action_area2">
+ <widget class="GtkHButtonBox" id="dialog-action_area3">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
+ <widget class="GtkButton" id="node_properties_apply_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-apply</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-10</property>
+ </widget>
+ </child>
+
+ <child>
<widget class="GtkButton" id="node_properties_cancel_button">
<property name="visible">True</property>
<property name="can_default">True</property>
@@ -879,6 +898,7 @@ Connect some nodes up and double click one. You'll get it.</property>
<widget class="GtkButton" id="node_properties_ok_button">
<property name="visible">True</property>
<property name="can_default">True</property>
+ <property name="has_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-ok</property>
<property name="use_stock">True</property>
@@ -908,7 +928,6 @@ Connect some nodes up and double click one. You'll get it.</property>
<child>
<widget class="GtkSpinButton" id="node_properties_note_spinbutton">
<property name="visible">True</property>
- <property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="climb_rate">1</property>
<property name="digits">0</property>
@@ -986,8 +1005,8 @@ Connect some nodes up and double click one. You'll get it.</property>
<child>
<widget class="GtkSpinButton" id="node_properties_duration_spinbutton">
<property name="visible">True</property>
- <property name="sensitive">False</property>
<property name="can_focus">True</property>
+ <property name="has_focus">True</property>
<property name="climb_rate">1</property>
<property name="digits">2</property>
<property name="numeric">True</property>
diff --git a/src/gui/main.cpp b/src/gui/main.cpp
index c522898..e1e86ea 100644
--- a/src/gui/main.cpp
+++ b/src/gui/main.cpp
@@ -51,6 +51,11 @@ main(int argc, char** argv)
cout << "No quantization." << endl;
machine = file_driver->learn(filename);
}
+
+ if (!machine) {
+ cout << "Not a MIDI file. Attempting to load as Machina file." << endl;
+ machine = Loader().load(filename);
+ }
}
if (!machine)
diff --git a/util/machina2dot b/util/machina2dot
index 726f98a..22cfbf0 100755
--- a/util/machina2dot
+++ b/util/machina2dot
@@ -15,10 +15,50 @@ parser.parse_into_model(model, "file:" + sys.argv[1])
print """
digraph finite_state_machine {
rankdir=LR;
- node [ shape = circle ];
+ {
+ node [ shape = doublecircle ];
""",
-node_durations = { }
+written_nodes = {}
+node_durations = {}
+invis_id = 0;
+
+
+# Initial selectors
+
+initial_selectors_query = RDF.SPARQLQuery("""
+PREFIX machina: <http://drobilla.net/ns/machina#>
+SELECT DISTINCT ?n ?dur ?note WHERE {
+ ?m machina:initialNode ?n .
+ ?n a machina:SelectorNode ;
+ machina:duration ?dur .
+ OPTIONAL { ?n machina:enterAction ?a .
+ ?a machina:midiNote ?note }
+}
+""")
+
+for result in initial_selectors_query.execute(model):
+ node_id = result['n'].blank_identifier
+ duration = float(result['dur'].literal_value['string'])
+ written_nodes[node_id] = True;
+ node_durations[node_id] = duration
+ print "\t{ node [ style = invis ] ",
+ print "invis%d" % invis_id, " }"
+
+ label = "d=%.1f" % duration
+ if result['note']:
+ label += "\\nn=%s" % result['note'].literal_value['string']
+
+ print '\t', node_id, "[ label=\"%s\" ]" % label
+ print '\t', "invis%d" % invis_id, " -> ", node_id
+ invis_id += 1
+
+print """ } {
+ node [ shape = circle ];
+"""
+
+
+# Initial non-selectors
initial_nodes_query = RDF.SPARQLQuery("""
PREFIX machina: <http://drobilla.net/ns/machina#>
@@ -31,11 +71,14 @@ SELECT DISTINCT ?n ?dur ?note WHERE {
}
""")
-invis_id = 0;
-
for result in initial_nodes_query.execute(model):
node_id = result['n'].blank_identifier
duration = float(result['dur'].literal_value['string'])
+
+ if written_nodes.has_key(node_id):
+ continue
+
+ written_nodes[node_id] = True;
node_durations[node_id] = duration
print "\t{ node [ style = invis ] ",
print "invis%d" % invis_id, " }"
@@ -49,6 +92,47 @@ for result in initial_nodes_query.execute(model):
invis_id += 1
+# Non-initial selectors
+
+print """ } {
+ node [ shape = doublecircle ];
+"""
+
+selectors_query = RDF.SPARQLQuery("""
+PREFIX machina: <http://drobilla.net/ns/machina#>
+SELECT DISTINCT ?n ?dur ?note WHERE {
+ ?m machina:node ?n .
+ ?n a machina:SelectorNode ;
+ machina:duration ?dur .
+ OPTIONAL { ?n machina:enterAction ?a .
+ ?a machina:midiNote ?note }
+}
+""")
+
+
+for result in selectors_query.execute(model):
+ node_id = result['n'].blank_identifier
+ duration = float(result['dur'].literal_value['string'])
+
+ if written_nodes.has_key(node_id):
+ continue
+
+ node_durations[node_id] = duration
+
+ label = "d=%.1f" % duration
+ if result['note']:
+ label += "\\nn=%s" % result['note'].literal_value['string']
+
+ print '\t', node_id, "[ label=\"%s\" ]" % label
+
+
+
+# Non-initial non-selectors
+
+print """ } {
+ node [ shape = circle ];
+"""
+
nodes_query = RDF.SPARQLQuery("""
PREFIX machina: <http://drobilla.net/ns/machina#>
SELECT DISTINCT ?n ?dur ?note WHERE {
@@ -60,9 +144,14 @@ SELECT DISTINCT ?n ?dur ?note WHERE {
}
""")
+
for result in nodes_query.execute(model):
node_id = result['n'].blank_identifier
duration = float(result['dur'].literal_value['string'])
+
+ if written_nodes.has_key(node_id):
+ continue
+
node_durations[node_id] = duration
label = "d=%.1f" % duration
@@ -71,7 +160,9 @@ for result in nodes_query.execute(model):
print '\t', node_id, "[ label=\"%s\" ]" % label
-
+
+# Edges
+
edge_query = RDF.SPARQLQuery("""
PREFIX machina: <http://drobilla.net/ns/machina#>
SELECT DISTINCT ?tail ?head ?prob WHERE {
@@ -86,6 +177,8 @@ for edge in edge_query.execute(model):
print '\t', edge['tail'].blank_identifier, ' -> ',
print edge['head'].blank_identifier, ' ',
print "[ label = \"%1.2f\"" % float(edge['prob'].literal_value['string']),
- print "minlen = ", node_durations[edge['tail'].blank_identifier], " ];"
+ print "minlen = ", node_durations[edge['tail'].blank_identifier]+0.1, " ];"
-print "}"
+print """
+ }
+}"""