diff options
author | David Robillard <d@drobilla.net> | 2007-04-02 01:52:53 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2007-04-02 01:52:53 +0000 |
commit | db6f6e87dc4ff620f399597913f14a3b4eda277f (patch) | |
tree | 4258f8cc7f2a841fd41ce9dac222919f0ee98eeb | |
parent | 69ad86f21555d28f5065923eea06ccc3cc4f4ce5 (diff) | |
download | machina-db6f6e87dc4ff620f399597913f14a3b4eda277f.tar.gz machina-db6f6e87dc4ff620f399597913f14a3b4eda277f.tar.bz2 machina-db6f6e87dc4ff620f399597913f14a3b4eda277f.zip |
Edge label toggling.
Made state properties dialog actually work.
Other things...
git-svn-id: http://svn.drobilla.net/lad/machina@390 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r-- | src/engine/Engine.cpp | 24 | ||||
-rw-r--r-- | src/engine/JackDriver.cpp | 13 | ||||
-rw-r--r-- | src/engine/Loader.cpp | 7 | ||||
-rw-r--r-- | src/engine/MachineBuilder.cpp | 24 | ||||
-rw-r--r-- | src/engine/machina/Driver.hpp | 3 | ||||
-rw-r--r-- | src/engine/machina/Engine.hpp | 1 | ||||
-rw-r--r-- | src/engine/machina/JackDriver.hpp | 2 | ||||
-rw-r--r-- | src/gui/EdgeView.cpp | 21 | ||||
-rw-r--r-- | src/gui/EdgeView.hpp | 3 | ||||
-rw-r--r-- | src/gui/MachinaGUI.cpp | 24 | ||||
-rw-r--r-- | src/gui/MachinaGUI.hpp | 4 | ||||
-rw-r--r-- | src/gui/NodePropertiesWindow.cpp | 19 | ||||
-rw-r--r-- | src/gui/NodePropertiesWindow.hpp | 4 | ||||
-rw-r--r-- | src/gui/machina.glade | 33 | ||||
-rw-r--r-- | src/gui/main.cpp | 5 | ||||
-rwxr-xr-x | util/machina2dot | 107 |
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 """ + } +}""" |