From dd6be02a7478225f19f02432919b64b96b733172 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 30 Mar 2007 22:32:07 +0000 Subject: Canvas auto-layout uses durations like graphviz diagrams. Learning fixes. Added duration spinbutton to MIDI Import dialog. git-svn-id: http://svn.drobilla.net/lad/machina@381 a436a847-0d15-0410-975c-d299462d15a1 --- src/engine/Edge.cpp | 12 ++++++------ src/engine/JackDriver.cpp | 7 +------ src/engine/Machine.cpp | 19 ++++++++++--------- src/engine/Node.cpp | 4 ++-- src/engine/SMFDriver.cpp | 13 +++++++------ src/engine/machina/Edge.hpp | 18 +++++++++--------- src/gui/EdgeView.cpp | 7 +++++++ src/gui/EdgeView.hpp | 2 ++ src/gui/MachinaCanvas.cpp | 22 +++++++++++----------- src/gui/MachinaGUI.cpp | 18 +++++++++++++++++- 10 files changed, 72 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/engine/Edge.cpp b/src/engine/Edge.cpp index 1a7d236..f982cda 100644 --- a/src/engine/Edge.cpp +++ b/src/engine/Edge.cpp @@ -34,21 +34,21 @@ Edge::write_state(Raul::RDFWriter& writer) RdfId(RdfId::RESOURCE, "rdf:type"), RdfId(RdfId::RESOURCE, "machina:Edge")); - SharedPtr src = _src.lock(); - SharedPtr dst = _dst; + SharedPtr tail = _tail.lock(); + SharedPtr head = _head; - if (!src || !dst) + if (!tail || !head) return; - assert(src->id() && dst->id()); + assert(tail->id() && head->id()); writer.write(_id, RdfId(RdfId::RESOURCE, "machina:tail"), - src->id()); + tail->id()); writer.write(_id, RdfId(RdfId::RESOURCE, "machina:head"), - dst->id()); + head->id()); writer.write(_id, RdfId(RdfId::RESOURCE, "machina:probability"), diff --git a/src/engine/JackDriver.cpp b/src/engine/JackDriver.cpp index d389e2a..606a8ff 100644 --- a/src/engine/JackDriver.cpp +++ b/src/engine/JackDriver.cpp @@ -182,12 +182,9 @@ JackDriver::write_event(Raul::BeatTime time, void JackDriver::on_process(jack_nframes_t nframes) { - //using namespace std; - //std::cerr << "> ======================================================\n"; - _cycle_time.set_bpm(_bpm.get()); - // (start time set at end of previous cycle) + // (N.B. start time set at end of previous cycle) _cycle_time.set_offset(0); _cycle_time.set_length(nframes); @@ -256,8 +253,6 @@ JackDriver::on_process(jack_nframes_t nframes) /* Remember the last machine run, in case a switch happens and * we need to finalize it next cycle. */ _last_machine = machine; - - //std::cerr << "< ======================================================\n"; } diff --git a/src/engine/Machine.cpp b/src/engine/Machine.cpp index 600dd3d..43fd280 100644 --- a/src/engine/Machine.cpp +++ b/src/engine/Machine.cpp @@ -56,6 +56,7 @@ void Machine::add_node(SharedPtr node) { //cerr << "ADDING NODE " << node.get() << endl; + assert(_nodes.find(node) == _nodes.end()); _nodes.push_back(node); } @@ -78,6 +79,8 @@ Machine::reset() if (node->is_active()) node->exit(_sink.lock(), _time); + + assert(! node->is_active()); } } @@ -150,6 +153,7 @@ Machine::exit_node(SharedPtr sink, const SharedPtr node) { node->exit(sink, _time); assert(!node->is_active()); + for (size_t i=0; i < MAX_ACTIVE_NODES; ++i) { if (_active_nodes[i] == node) { _active_nodes[i].reset(); @@ -161,13 +165,15 @@ Machine::exit_node(SharedPtr sink, const SharedPtr node) for (Node::Edges::const_iterator s = node->outgoing_edges().begin(); s != node->outgoing_edges().end(); ++s) { + assert((*s)->head() != node); // no loops + const double rand_normal = rand() / (double)RAND_MAX; // [0, 1] if (rand_normal <= (*s)->probability()) { - SharedPtr dst = (*s)->dst(); + SharedPtr head = (*s)->head(); - if (!dst->is_active()) - enter_node(sink, dst); + if (!head->is_active()) + enter_node(sink, head); } } } @@ -187,7 +193,6 @@ Machine::run(const Raul::TimeSlice& time) { using namespace std; if (_is_finished) { - cerr << "FINISHED\n"; return 0; } @@ -195,8 +200,6 @@ Machine::run(const Raul::TimeSlice& time) const BeatCount cycle_end = _time + time.length_beats(); - //std::cerr << "Start: " << _time << std::endl; - assert(_is_activated); // Initial run, enter all initial states @@ -249,8 +252,6 @@ Machine::run(const Raul::TimeSlice& time) } - //std::cerr << "Done: " << this_time << std::endl; - assert(this_time <= time.length_beats()); return this_time; } @@ -263,7 +264,7 @@ Machine::run(const Raul::TimeSlice& time) void Machine::learn(SharedPtr learn) { - std::cerr << "LEARN\n"; + std::cerr << "Learn" << std::endl; /*LearnRequest request(node, SharedPtr(new MidiAction(4, NULL)), diff --git a/src/engine/Node.cpp b/src/engine/Node.cpp index 768422e..e51e33d 100644 --- a/src/engine/Node.cpp +++ b/src/engine/Node.cpp @@ -92,7 +92,7 @@ Node::exit(SharedPtr sink, BeatTime time) void Node::add_outgoing_edge(SharedPtr edge) { - assert(edge->src().lock().get() == this); + assert(edge->tail().lock().get() == this); _outgoing_edges.push_back(edge); } @@ -112,7 +112,7 @@ Node::remove_outgoing_edges_to(SharedPtr node) Edges::iterator next = i; ++next; - if ((*i)->dst() == node) + if ((*i)->head() == node) _outgoing_edges.erase(i); i = next; diff --git a/src/engine/SMFDriver.cpp b/src/engine/SMFDriver.cpp index 33fc686..5b6d940 100644 --- a/src/engine/SMFDriver.cpp +++ b/src/engine/SMFDriver.cpp @@ -63,6 +63,8 @@ SMFDriver::learn(const string& filename, unsigned track, double q, Raul::BeatTim else learn_track(m, reader, track, q, max_duration); + m->reset(); + if (m->nodes().size() > 1) return m; else @@ -89,6 +91,8 @@ SMFDriver::learn(const string& filename, double q, Raul::BeatTime max_duration) learn_track(m, reader, t, q, max_duration); } + m->reset(); + if (m->nodes().size() > 1) return m; else @@ -246,7 +250,7 @@ SMFDriver::learn_track(SharedPtr m, // (these happen after polyphonic sections) if (is_delay_node(connect_node) && connect_node->duration() == 0 && connect_node->outgoing_edges().size() == 1 - && (*connect_node->outgoing_edges().begin())->dst() == resolved) { + && (*connect_node->outgoing_edges().begin())->head() == resolved) { connect_node->outgoing_edges().clear(); assert(connect_node->outgoing_edges().empty()); connect_node->set_enter_action(resolved->enter_action()); @@ -301,11 +305,8 @@ SMFDriver::learn_track(SharedPtr m, active_nodes.clear(); } - if (added_nodes > 0) - /*if (initial_node->outgoing_edges().size() == 1) - (*initial_node->outgoing_edges().begin())->dst()->set_initial(true); - else*/ - m->add_node(initial_node); + if (m->nodes().find(initial_node) == m->nodes().end()) + m->add_node(initial_node); } diff --git a/src/engine/machina/Edge.hpp b/src/engine/machina/Edge.hpp index 7f14788..e8e4ec0 100644 --- a/src/engine/machina/Edge.hpp +++ b/src/engine/machina/Edge.hpp @@ -34,19 +34,19 @@ class Node; class Edge : public Raul::Stateful, public boost::noncopyable { public: - Edge(WeakPtr src, SharedPtr dst) + Edge(WeakPtr tail, SharedPtr head) : _probability(1.0f) - , _src(src) - , _dst(dst) + , _tail(tail) + , _head(head) {} void write_state(Raul::RDFWriter& writer); - WeakPtr src() { return _src; } - SharedPtr dst() { return _dst; } + WeakPtr tail() { return _tail; } + SharedPtr head() { return _head; } - void set_src(WeakPtr src) { _src = src; } - void set_dst(SharedPtr dst) { _dst = dst; } + void set_tail(WeakPtr tail) { _tail = tail; } + void set_head(SharedPtr head) { _head = head; } inline float probability() { return _probability.get(); } inline void set_probability(float p) { _probability.set(p); } @@ -54,8 +54,8 @@ public: private: Raul::DoubleBuffer _probability; - WeakPtr _src; - SharedPtr _dst; + WeakPtr _tail; + SharedPtr _head; }; diff --git a/src/gui/EdgeView.cpp b/src/gui/EdgeView.cpp index 4817eca..fccf8d5 100644 --- a/src/gui/EdgeView.cpp +++ b/src/gui/EdgeView.cpp @@ -33,6 +33,13 @@ EdgeView::EdgeView(SharedPtr canvas, { } + +double +EdgeView::length_hint() const +{ + return _edge->tail().lock()->duration() * 10; +} + void EdgeView::update_label() diff --git a/src/gui/EdgeView.hpp b/src/gui/EdgeView.hpp index c61d0cf..c394d49 100644 --- a/src/gui/EdgeView.hpp +++ b/src/gui/EdgeView.hpp @@ -34,6 +34,8 @@ public: SharedPtr edge() { return _edge; } void update_label(); + + virtual double length_hint() const; private: bool on_event(GdkEvent* ev); diff --git a/src/gui/MachinaCanvas.cpp b/src/gui/MachinaCanvas.cpp index a6a565e..134b885 100644 --- a/src/gui/MachinaCanvas.cpp +++ b/src/gui/MachinaCanvas.cpp @@ -115,25 +115,25 @@ MachinaCanvas::canvas_event(GdkEvent* event) void MachinaCanvas::connect_node(boost::shared_ptr src, - boost::shared_ptr dst) + boost::shared_ptr head) { - SharedPtr edge(new Machina::Edge(src->node(), dst->node())); + SharedPtr edge(new Machina::Edge(src->node(), head->node())); src->node()->add_outgoing_edge(edge); boost::shared_ptr c(new EdgeView(shared_from_this(), - src, dst, edge)); + src, head, edge)); src->add_connection(c); - dst->add_connection(c); + head->add_connection(c); add_connection(c); } void MachinaCanvas::disconnect_node(boost::shared_ptr src, - boost::shared_ptr dst) + boost::shared_ptr head) { - src->node()->remove_outgoing_edges_to(dst->node()); - remove_connection(src, dst); + src->node()->remove_outgoing_edges_to(head->node()); + remove_connection(src, head); #if 0 boost::shared_ptr input @@ -213,16 +213,16 @@ MachinaCanvas::build(SharedPtr machine) for (Machina::Node::Edges::const_iterator e = view->node()->outgoing_edges().begin(); e != view->node()->outgoing_edges().end(); ++e) { - SharedPtr dst_view = views[(*e)->dst()]; - if (!dst_view) { + SharedPtr head_view = views[(*e)->head()]; + if (!head_view) { cerr << "WARNING: Edge to node with no view" << endl; continue; } boost::shared_ptr c(new EdgeView(shared_from_this(), - view, dst_view, (*e))); + view, head_view, (*e))); view->add_connection(c); - dst_view->add_connection(c); + head_view->add_connection(c); add_connection(c); } diff --git a/src/gui/MachinaGUI.cpp b/src/gui/MachinaGUI.cpp index ffbfb5a..de432aa 100644 --- a/src/gui/MachinaGUI.cpp +++ b/src/gui/MachinaGUI.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -426,6 +427,18 @@ MachinaGUI::menu_import_midi() Gtk::FILE_CHOOSER_ACTION_OPEN); dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK); + + Gtk::HBox* extra_widget = Gtk::manage(new Gtk::HBox()); + Gtk::SpinButton* length_sb = Gtk::manage(new Gtk::SpinButton()); + length_sb->set_increments(1, 10); + length_sb->set_range(0, INT_MAX); + length_sb->set_value(0); + extra_widget->pack_start(*Gtk::manage(new Gtk::Label("")), true, true); + extra_widget->pack_start(*Gtk::manage(new Gtk::Label("Maximum Length (0 = unlimited): ")), false, false); + extra_widget->pack_start(*length_sb, false, false); + dialog.set_extra_widget(*extra_widget); + extra_widget->show_all(); + /*Gtk::HBox* extra_widget = Gtk::manage(new Gtk::HBox()); Gtk::SpinButton* track_sb = Gtk::manage(new Gtk::SpinButton()); @@ -444,7 +457,10 @@ MachinaGUI::menu_import_midi() SharedPtr file_driver(new Machina::SMFDriver()); //SharedPtr machine = file_driver->learn(dialog.get_uri(), // track_sb->get_value_as_int()); - SharedPtr machine = file_driver->learn(dialog.get_filename(), 0.0, 16.0); + + double length = length_sb->get_value_as_int(); + + SharedPtr machine = file_driver->learn(dialog.get_filename(), 0.0, length); if (machine) { dialog.hide(); -- cgit v1.2.1