diff options
-rw-r--r-- | src/engine/Action.cpp | 3 | ||||
-rw-r--r-- | src/engine/JackDriver.cpp | 10 | ||||
-rw-r--r-- | src/engine/Node.cpp | 25 | ||||
-rw-r--r-- | src/engine/SMFDriver.cpp | 60 | ||||
-rw-r--r-- | src/engine/machina/MidiAction.hpp | 9 | ||||
-rw-r--r-- | src/engine/machina/Node.hpp | 5 | ||||
-rw-r--r-- | src/gui/MachinaGUI.cpp | 12 | ||||
-rw-r--r-- | src/gui/MachinaGUI.hpp | 4 | ||||
-rw-r--r-- | src/gui/NodeView.cpp | 4 | ||||
-rw-r--r-- | src/gui/machina.glade | 59 |
10 files changed, 133 insertions, 58 deletions
diff --git a/src/engine/Action.cpp b/src/engine/Action.cpp index a893d74..471dfa8 100644 --- a/src/engine/Action.cpp +++ b/src/engine/Action.cpp @@ -24,6 +24,9 @@ void Action::write_state(Raul::RDFWriter& writer) { using Raul::RdfId; + + if (!_id) + set_id(writer.blank_id()); writer.write(_id, RdfId(RdfId::RESOURCE, "rdf:type"), diff --git a/src/engine/JackDriver.cpp b/src/engine/JackDriver.cpp index b22ad85..0261dd5 100644 --- a/src/engine/JackDriver.cpp +++ b/src/engine/JackDriver.cpp @@ -193,10 +193,12 @@ JackDriver::on_process(jack_nframes_t nframes) machine->set_sink(shared_from_this()); // Machine was switched since last cycle, finalize old machine. - if (_last_machine && machine != _last_machine) { - _last_machine->reset(); // Exit all active states - assert(_last_machine.use_count() > 1); // Realtime, can't delete - _last_machine.reset(); // Cut our reference + if (machine != _last_machine) { + if (_last_machine) { + _last_machine->reset(); // Exit all active states + assert(_last_machine.use_count() > 1); // Realtime, can't delete + _last_machine.reset(); // Cut our reference + } _machine_changed.post(); // Signal we're done with it } diff --git a/src/engine/Node.cpp b/src/engine/Node.cpp index fbf02fe..4a1ded0 100644 --- a/src/engine/Node.cpp +++ b/src/engine/Node.cpp @@ -68,7 +68,7 @@ Node::enter(SharedPtr<Raul::MIDISink> sink, BeatTime time) //cerr << "ENTER " << time << endl; _is_active = true; _enter_time = time; - if (_enter_action) + if (sink && _enter_action) _enter_action->execute(sink, time); } @@ -77,7 +77,7 @@ void Node::exit(SharedPtr<Raul::MIDISink> sink, BeatTime time) { //cerr << "EXIT " << time << endl; - if (_exit_action) + if (sink && _exit_action) _exit_action->execute(sink, time); _is_active = false; _enter_time = 0; @@ -131,13 +131,22 @@ Node::write_state(Raul::RDFWriter& writer) RdfId(RdfId::RESOURCE, "machina:duration"), Raul::Atom((float)_duration)); - writer.write(_id, - RdfId(RdfId::RESOURCE, "machina:enterAction"), - _enter_action->id()); - _enter_action->write_state(writer); + if (_enter_action) { + _enter_action->write_state(writer); + + writer.write(_id, + RdfId(RdfId::RESOURCE, "machina:enterAction"), + _enter_action->id()); + } + + if (_exit_action) { + _exit_action->write_state(writer); + + writer.write(_id, + RdfId(RdfId::RESOURCE, "machina:exitAction"), + _exit_action->id()); + } - _exit_action->write_state(writer); - /*for (Node::Edges::const_iterator e = _outgoing_edges.begin(); e != _outgoing_edges.end(); ++e) (*e)->write_state(writer);*/ diff --git a/src/engine/SMFDriver.cpp b/src/engine/SMFDriver.cpp index dd60903..181da52 100644 --- a/src/engine/SMFDriver.cpp +++ b/src/engine/SMFDriver.cpp @@ -15,10 +15,14 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <list> #include <iostream> #include <glibmm/convert.h> +#include <raul/midi_events.h> #include <raul/SMFWriter.h> +#include <raul/SMFReader.h> #include "machina/Machine.hpp" +#include "machina/Edge.hpp" #include "machina/SMFDriver.hpp" using namespace std; @@ -37,8 +41,64 @@ SMFDriver::learn(const Glib::ustring& uri) const string filename = Glib::filename_from_uri(uri); std::cerr << "Learn MIDI: " << filename << std::endl; + SharedPtr<Machine> m(new Machine()); + list<SharedPtr<Node> > active_nodes; + SharedPtr<Node> connect_node(new Node()); + connect_node->set_initial(true); + m->add_node(connect_node); + + Raul::SMFReader reader; + reader.open(filename); + Raul::BeatTime t = 0; + unsigned char buf[4]; + uint32_t ev_size; + uint32_t ev_time; + while (reader.read_event(4, buf, &ev_size, &ev_time) >= 0) { + t += ev_time / (double)reader.ppqn(); + cerr << "t = " << t << endl; + if (ev_size > 0) { + if ((buf[0] & 0xF0) == MIDI_CMD_NOTE_ON) { + cerr << "NOTE ON: " << (int)buf[1] << endl; + SharedPtr<Node> node(new Node()); + node->add_enter_action(SharedPtr<Action>(new MidiAction(ev_size, buf))); + connect_node->add_outgoing_edge(SharedPtr<Edge>(new Edge(connect_node, node))); + node->enter(SharedPtr<Raul::MIDISink>(), t); + active_nodes.push_back(node); + } else if ((buf[0] & 0xF0) == MIDI_CMD_NOTE_OFF) { + cerr << "NOTE OFF: " << (int)buf[1] << endl; + for (list<SharedPtr<Node> >::iterator i = active_nodes.begin(); + i != active_nodes.end(); ++i) { + SharedPtr<MidiAction> action = PtrCast<MidiAction>((*i)->enter_action()); + if (!action) + continue; + + const size_t ev_size = action->event_size(); + const unsigned char* ev = action->event(); + if (ev_size == 3 && (ev[0] & 0xF0) == MIDI_CMD_NOTE_ON + && ev[1] == buf[1]) { + cerr << "FOUND MATCHING NOTE ON!\n"; + (*i)->add_exit_action(SharedPtr<Action>(new MidiAction(ev_size, buf))); + (*i)->set_duration(t - (*i)->enter_time()); + (*i)->exit(SharedPtr<Raul::MIDISink>(), t); + m->add_node((*i)); + if (active_nodes.size() == 1) + connect_node = (*i); + active_nodes.erase(i); + break; + } + } + } + } + /*std::cerr << "Event, size = " << ev_size << ", time = " << ev_time << std::endl; + cerr.flags(ios::hex); + for (uint32_t i=0; i < ev_size; ++i) { + cerr << "0x" << (int)buf[i] << " "; + } + cerr.flags(ios::dec); + cerr << endl;*/ + } return m; } diff --git a/src/engine/machina/MidiAction.hpp b/src/engine/machina/MidiAction.hpp index 2a9f91d..60d9189 100644 --- a/src/engine/machina/MidiAction.hpp +++ b/src/engine/machina/MidiAction.hpp @@ -34,6 +34,9 @@ class MidiAction : public Action { public: ~MidiAction(); + MidiAction(size_t size, + const unsigned char* event); + static SharedPtr<MidiAction> create(SharedPtr<Raul::Maid> maid, size_t size, const unsigned char* event) @@ -43,6 +46,9 @@ public: return ret; } + size_t event_size() { return _size; } + byte* event() { return _event.get(); } + bool set_event(size_t size, const byte* event); void execute(SharedPtr<Raul::MIDISink> driver, Raul::BeatTime time); @@ -50,8 +56,7 @@ public: virtual void write_state(Raul::RDFWriter& writer); private: - MidiAction(size_t size, - const unsigned char* event); + size_t _size; const size_t _max_size; diff --git a/src/engine/machina/Node.hpp b/src/engine/machina/Node.hpp index bd1a66e..2f9c2e4 100644 --- a/src/engine/machina/Node.hpp +++ b/src/engine/machina/Node.hpp @@ -48,10 +48,13 @@ public: void add_enter_action(SharedPtr<Action> action); void remove_enter_action(SharedPtr<Action> action); - + void add_exit_action(SharedPtr<Action> action); void remove_exit_action(SharedPtr<Action> action); + SharedPtr<Action> enter_action() { return _enter_action; } + SharedPtr<Action> exit_action() { return _exit_action; } + void enter(SharedPtr<Raul::MIDISink> driver, BeatTime time); void exit(SharedPtr<Raul::MIDISink> driver, BeatTime time); diff --git a/src/gui/MachinaGUI.cpp b/src/gui/MachinaGUI.cpp index 65ecb13..121e25a 100644 --- a/src/gui/MachinaGUI.cpp +++ b/src/gui/MachinaGUI.cpp @@ -115,7 +115,7 @@ MachinaGUI::MachinaGUI(SharedPtr<Machina::Engine> engine) xml->get_widget("save_menuitem", _menu_file_save); xml->get_widget("save_as_menuitem", _menu_file_save_as); xml->get_widget("quit_menuitem", _menu_file_quit); - xml->get_widget("learn_midi_menuitem", _menu_learn_midi); + xml->get_widget("import_midi_menuitem", _menu_import_midi); xml->get_widget("export_midi_menuitem", _menu_export_midi); xml->get_widget("view_toolbar_menuitem", _menu_view_toolbar); //xml->get_widget("view_refresh_menuitem", _menu_view_refresh); @@ -154,8 +154,8 @@ MachinaGUI::MachinaGUI(SharedPtr<Machina::Engine> engine) sigc::mem_fun(this, &MachinaGUI::menu_file_save_as)); _menu_file_quit->signal_activate().connect( sigc::mem_fun(this, &MachinaGUI::menu_file_quit)); - _menu_learn_midi->signal_activate().connect( - sigc::mem_fun(this, &MachinaGUI::menu_learn_midi)); + _menu_import_midi->signal_activate().connect( + sigc::mem_fun(this, &MachinaGUI::menu_import_midi)); _menu_export_midi->signal_activate().connect( sigc::mem_fun(this, &MachinaGUI::menu_export_midi)); //_menu_view_refresh->signal_activate().connect( @@ -437,7 +437,7 @@ MachinaGUI::menu_file_save_as() void -MachinaGUI::menu_learn_midi() +MachinaGUI::menu_import_midi() { Gtk::FileChooserDialog dialog(*_main_window, "Learn from MIDI file", Gtk::FILE_CHOOSER_ACTION_OPEN); dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); @@ -448,6 +448,10 @@ MachinaGUI::menu_learn_midi() if (result == Gtk::RESPONSE_OK) { SharedPtr<Machina::SMFDriver> file_driver(new Machina::SMFDriver()); SharedPtr<Machina::Machine> machine = file_driver->learn(dialog.get_uri()); + machine->activate(); + machine->reset(); + _engine->driver()->set_machine(machine); + _canvas->build(machine); } } diff --git a/src/gui/MachinaGUI.hpp b/src/gui/MachinaGUI.hpp index 962a6f9..0e507fc 100644 --- a/src/gui/MachinaGUI.hpp +++ b/src/gui/MachinaGUI.hpp @@ -59,7 +59,7 @@ protected: void menu_file_open(); void menu_file_save(); void menu_file_save_as(); - void menu_learn_midi(); + void menu_import_midi(); void menu_export_midi(); //void show_messages_toggled(); void show_toolbar_toggled(); @@ -100,7 +100,7 @@ protected: Gtk::MenuItem* _menu_file_save; Gtk::MenuItem* _menu_file_save_as; Gtk::MenuItem* _menu_file_quit; - Gtk::MenuItem* _menu_learn_midi; + Gtk::MenuItem* _menu_import_midi; Gtk::MenuItem* _menu_export_midi; Gtk::MenuItem* _menu_help_about; Gtk::CheckMenuItem* _menu_view_toolbar; diff --git a/src/gui/NodeView.cpp b/src/gui/NodeView.cpp index 62be95b..f34c658 100644 --- a/src/gui/NodeView.cpp +++ b/src/gui/NodeView.cpp @@ -34,10 +34,11 @@ void NodeView::on_double_click(GdkEventButton*) { bool is_initial = _node->is_initial(); - std::cerr << "INITIAL " << is_initial; + std::cerr << "Initial: " << is_initial << std::endl; _node->set_initial( ! is_initial ); } + void NodeView::update_state() { @@ -52,3 +53,4 @@ NodeView::update_state() set_base_color(_old_color); } } + diff --git a/src/gui/machina.glade b/src/gui/machina.glade index d82f528..c0d1b87 100644 --- a/src/gui/machina.glade +++ b/src/gui/machina.glade @@ -77,6 +77,28 @@ </child> <child> + <widget class="GtkImageMenuItem" id="import_midi_menuitem"> + <property name="visible">True</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"/> + <accelerator key="I" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image8"> + <property name="visible">True</property> + <property name="stock">gtk-media-record</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> <widget class="GtkImageMenuItem" id="export_midi_menuitem"> <property name="visible">True</property> <property name="label" translatable="yes">_Export MIDI...</property> @@ -85,7 +107,7 @@ <accelerator key="E" modifiers="GDK_CONTROL_MASK" signal="activate"/> <child internal-child="image"> - <widget class="GtkImage" id="image6"> + <widget class="GtkImage" id="image9"> <property name="visible">True</property> <property name="stock">gtk-convert</property> <property name="icon_size">1</property> @@ -118,41 +140,6 @@ </child> <child> - <widget class="GtkMenuItem" id="machine_menu"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Machine</property> - <property name="use_underline">True</property> - - <child> - <widget class="GtkMenu" id="machine_menu_menu"> - - <child> - <widget class="GtkImageMenuItem" id="learn_midi_menuitem"> - <property name="visible">True</property> - <property name="label" translatable="yes">Learn 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"/> - <accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/> - - <child internal-child="image"> - <widget class="GtkImage" id="image7"> - <property name="visible">True</property> - <property name="stock">gtk-media-record</property> - <property name="icon_size">1</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - </child> - </widget> - </child> - </widget> - </child> - </widget> - </child> - - <child> <widget class="GtkMenuItem" id="view_menu"> <property name="visible">True</property> <property name="label" translatable="yes">_View</property> |