diff options
-rw-r--r-- | src/JackActions.cpp | 88 | ||||
-rw-r--r-- | src/JackDriver.cpp | 102 | ||||
-rw-r--r-- | src/JackNodeFactory.cpp | 42 | ||||
-rw-r--r-- | src/Loader.cpp | 221 | ||||
-rw-r--r-- | src/Machine.cpp | 221 | ||||
-rw-r--r-- | src/Node.cpp | 104 | ||||
-rw-r--r-- | src/engine/JackDriver.cpp | 9 | ||||
-rw-r--r-- | src/engine/Machine.cpp | 20 | ||||
-rw-r--r-- | src/engine/machina/Machine.hpp | 2 | ||||
-rw-r--r-- | src/gui/MachinaCanvas.cpp | 176 | ||||
-rw-r--r-- | src/gui/MachinaCanvas.hpp | 17 | ||||
-rw-r--r-- | src/gui/MachinaGUI.hpp | 7 | ||||
-rw-r--r-- | src/gui/Makefile.am | 4 |
13 files changed, 119 insertions, 894 deletions
diff --git a/src/JackActions.cpp b/src/JackActions.cpp deleted file mode 100644 index 9a2ee03..0000000 --- a/src/JackActions.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* This file is part of Machina. - * Copyright (C) 2007 Dave Robillard <http://drobilla.net> - * - * Machina is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Machina is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <iostream> -#include "JackActions.hpp" -#include "JackDriver.hpp" - -namespace Machina { - - -/* NOTE ON */ - -JackNoteOnAction::JackNoteOnAction(WeakPtr<JackDriver> driver, - unsigned char note_num) - : _driver(driver) - , _note_num(note_num) -{ -} - - -void -JackNoteOnAction::execute(Timestamp time) -{ - SharedPtr<JackDriver> driver = _driver.lock(); - if (!driver) - return; - - const FrameCount nframes = driver->current_cycle_nframes(); - const FrameCount offset = driver->stamp_to_offset(time); - - //std::cerr << offset << " \tNOTE ON:\t" << (int)_note_num << "\t@ " << time << std::endl; - - jack_midi_data_t ev[] = { 0x80, _note_num, 0x40 }; - - jack_midi_event_write( - jack_port_get_buffer(driver->output_port(), nframes), - offset, ev, 3, nframes); -} - - - -/* NOTE OFF */ - -JackNoteOffAction::JackNoteOffAction(WeakPtr<JackDriver> driver, - unsigned char note_num) - : _driver(driver) - , _note_num(note_num) -{ -} - - -void -JackNoteOffAction::execute(Timestamp time) -{ - SharedPtr<JackDriver> driver = _driver.lock(); - if (!driver) - return; - - const FrameCount nframes = driver->current_cycle_nframes(); - const FrameCount offset = driver->stamp_to_offset(time); - - //std::cerr << offset << " \tNOTE OFF:\t" << (int)_note_num << "\t@ " << time << std::endl; - - jack_midi_data_t ev[] = { 0x90, _note_num, 0x40 }; - - jack_midi_event_write( - jack_port_get_buffer(driver->output_port(), nframes), - offset, ev, 3, nframes); -} - - -} // namespace Machina - - diff --git a/src/JackDriver.cpp b/src/JackDriver.cpp deleted file mode 100644 index 3eacd49..0000000 --- a/src/JackDriver.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* This file is part of Machina. - * Copyright (C) 2007 Dave Robillard <http://drobilla.net> - * - * Machina is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Machina is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "JackDriver.hpp" - -#include <iostream> - -namespace Machina { - - -JackDriver::JackDriver() - : _output_port(NULL) - , _current_cycle_start(0) - , _current_cycle_nframes(0) -{ -} - - -void -JackDriver::attach(const std::string& client_name) -{ - Raul::JackDriver::attach(client_name); - - if (jack_client()) { - _output_port = jack_port_register(jack_client(), - "out", - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, - 0); - } -} - - -void -JackDriver::detach() -{ - jack_port_unregister(jack_client(), _output_port); - _output_port = NULL; - - Raul::JackDriver::detach(); -} - - -Timestamp -JackDriver::stamp_to_offset(Timestamp stamp) -{ - Timestamp ret = stamp - _current_cycle_start + _current_cycle_offset; - assert(ret < _current_cycle_offset + _current_cycle_nframes); - return ret; -} - - -void -JackDriver::on_process(jack_nframes_t nframes) -{ - //std::cerr << "======================================================\n"; - - _current_cycle_offset = 0; - _current_cycle_nframes = nframes; - - jack_midi_clear_buffer(jack_port_get_buffer(_output_port, nframes), nframes); - - while (true) { - - bool machine_done = ! _machine->run(_current_cycle_nframes); - - if (!machine_done) { - _current_cycle_start += _current_cycle_nframes; - break; - - } else { - const Timestamp finish_time = _machine->time(); - const FrameCount finish_offset = stamp_to_offset(finish_time); - - if (finish_offset >= _current_cycle_nframes) - break; - - _current_cycle_offset = stamp_to_offset(finish_time); - _current_cycle_nframes -= _current_cycle_offset; - _current_cycle_start = 0; - _machine->reset(); - } - } - - //std::cerr << "======================================================\n"; -} - - -} // namespace Machina diff --git a/src/JackNodeFactory.cpp b/src/JackNodeFactory.cpp deleted file mode 100644 index 1dcc380..0000000 --- a/src/JackNodeFactory.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* This file is part of Machina. - * Copyright (C) 2007 Dave Robillard <http://drobilla.net> - * - * Machina is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Machina is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "JackNodeFactory.hpp" -#include "JackActions.hpp" -#include "Node.hpp" - -namespace Machina { - - -SharedPtr<Node> -JackNodeFactory::create_node(Node::ID, unsigned char note, FrameCount duration) -{ - // FIXME: leaks like a sieve, obviously - - Node* n = new Node(duration); - JackNoteOnAction* a_enter = new JackNoteOnAction(_driver, note); - JackNoteOffAction* a_exit = new JackNoteOffAction(_driver, note); - - n->add_enter_action(a_enter); - n->add_exit_action(a_exit); - - return SharedPtr<Node>(n); -} - - -} // namespace Machina - diff --git a/src/Loader.cpp b/src/Loader.cpp deleted file mode 100644 index 9bb6336..0000000 --- a/src/Loader.cpp +++ /dev/null @@ -1,221 +0,0 @@ -/* This file is part of Machina. - * Copyright (C) 2007 Dave Robillard <http://drobilla.net> - * - * Machina is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Machina is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <iostream> -#include <map> -#include <raptor.h> -#include <rasqal.h> -#include <glibmm/ustring.h> -#include "raul/RDFQuery.h" -#include "Loader.hpp" -#include "Node.hpp" -#include "Edge.hpp" -#include "Machine.hpp" -#include "NodeFactory.hpp" - -using namespace Raul; -using std::cerr; using std::cout; using std::endl; - -namespace Machina { - - -/* -// FIXME: remove -Node* create_debug_node(const Node::ID& id, FrameCount duration) -{ - // leaks like a sieve, obviously - - Node* n = new Node(duration); - PrintAction* a_enter = new PrintAction(string("\t> ") + id); - PrintAction* a_exit = new PrintAction(string("\t< ") + id); - - n->add_enter_action(a_enter); - n->add_exit_action(a_exit); - - cerr << "dur: " << duration << endl; - - return n; -} -*/ - -Loader::Loader(SharedPtr<NodeFactory> node_factory, - SharedPtr<Namespaces> namespaces) - : _node_factory(node_factory) - , _namespaces(namespaces) -{ - if (!_namespaces) - _namespaces = SharedPtr<Namespaces>(new Namespaces()); - - (*_namespaces)[""] = "http://drobilla.net/ns/machina#"; - (*_namespaces)["xsd"] = "http://www.w3.org/2001/XMLSchema#"; -} - - -/** Load (create) all objects from an RDF into the engine. - * - * @param filename Filename to load objects from. - * @param parent Path of parent under which to load objects. - * @return whether or not load was successful. - */ -SharedPtr<Machine> -Loader::load(const Glib::ustring& filename) -{ - using Raul::RDFQuery; - SharedPtr<Machine> machine; - - rasqal_init(); - - unsigned char* document_uri_str = raptor_uri_filename_to_uri_string(filename.c_str()); - assert(document_uri_str); - raptor_uri* document_raptor_uri = raptor_new_uri(document_uri_str); - - if (!document_uri_str) - return machine; - - machine = SharedPtr<Machine>(new Machine()); - - Glib::ustring document_uri = (const char*)document_uri_str; - - string machine_uri = "<> "; - - cout << "[Loader] Loading " << machine_uri << " from " << document_uri << endl; - - typedef std::map<string, SharedPtr<Node> > Created; - Created created; - - - /* Get initial nodes */ - - Raul::RDFQuery query = Raul::RDFQuery(*_namespaces, Glib::ustring( - "SELECT DISTINCT ?initialNode ?midiNote ?duration FROM <") - + document_uri + "> WHERE {\n" + - machine_uri + " :initialNode ?initialNode .\n" - "?initialNode :midiNote ?midiNote ;\n" - " :duration ?duration .\n" - "}\n"); - - RDFQuery::Results results = query.run(document_uri); - - for (RDFQuery::Results::iterator i = results.begin(); i != results.end(); ++i) { - const Glib::ustring& node_uri = (*i)["initialNode"]; - const Glib::ustring& midi_note = (*i)["midiNote"]; - const Glib::ustring& duration = (*i)["duration"]; - - raptor_uri* node_raptor_uri - = raptor_new_uri((const unsigned char*)node_uri.c_str()); - - char* node_name = (char*) - raptor_uri_to_relative_uri_string(document_raptor_uri, node_raptor_uri); - - //cout << "Initial: " << node_name << ": " << midi_note << " - " << duration << endl; - - SharedPtr<Node> node = SharedPtr<Node>(_node_factory->create_node( - node_name, - strtol(midi_note.c_str(), NULL, 10), - strtol(duration.c_str(), NULL, 10))); - - node->set_initial(true); - //machine->add_node(string(node_name).substr(1), node); // (chop leading "#") - machine->add_node(node); - - created.insert(std::make_pair(node_uri.collate_key(), node)); - - raptor_free_uri(node_raptor_uri); - free(node_name); - } - - - /* Get remaining nodes */ - - query = Raul::RDFQuery(*_namespaces, Glib::ustring( - "SELECT DISTINCT ?node ?midiNote ?duration FROM <") - + document_uri + "> WHERE {\n" + - machine_uri + " :node ?node .\n" - "?node :midiNote ?midiNote ;\n" - " :duration ?duration .\n" - "}\n"); - - results = query.run(document_uri); - - for (RDFQuery::Results::iterator i = results.begin(); i != results.end(); ++i) { - const Glib::ustring& node_uri = (*i)["node"]; - const Glib::ustring& midi_note = (*i)["midiNote"]; - const Glib::ustring& duration = (*i)["duration"]; - - raptor_uri* node_raptor_uri - = raptor_new_uri((const unsigned char*)node_uri.c_str()); - - char* node_name = (char*) - raptor_uri_to_relative_uri_string(document_raptor_uri, node_raptor_uri); - - - SharedPtr<Node> node = SharedPtr<Node>(_node_factory->create_node( - node_name, - strtol(midi_note.c_str(), NULL, 10), - strtol(duration.c_str(), NULL, 10))); - - if (created.find(node_uri) == created.end()) { - //cout << "Node: " << node_name << ": " << midi_note << " - " << duration << endl; - //machine->add_node(string(node_name).substr(1), node); // (chop leading "#") - machine->add_node(node); - created.insert(std::make_pair(node_uri.collate_key(), node)); - } - - raptor_free_uri(node_raptor_uri); - free(node_name); - } - - - /* Get edges */ - - query = Raul::RDFQuery(*_namespaces, Glib::ustring( - "SELECT DISTINCT ?src ?edge ?dst FROM <") - + document_uri + "> WHERE {\n" + - machine_uri + " :edge ?edge .\n" - "?edge :tail ?src ;\n" - " :head ?dst .\n }"); - results = query.run(document_uri); - - for (RDFQuery::Results::iterator i = results.begin(); i != results.end(); ++i) { - const Glib::ustring& src_uri = (*i)["src"]; - const Glib::ustring& dst_uri = (*i)["dst"]; - - Created::iterator src_i = created.find(src_uri.collate_key()); - Created::iterator dst_i = created.find(dst_uri.collate_key()); - - if (src_i != created.end() && dst_i != created.end()) { - const SharedPtr<Node> src = src_i->second; - const SharedPtr<Node> dst = dst_i->second; - - src->add_outgoing_edge(SharedPtr<Edge>(new Edge(src, dst))); - - } else { - cerr << "[Loader] WARNING: Ignored edge between unknown nodes " - << src_uri << " -> " << dst_uri << endl; - } - - } - - free(document_uri_str); - raptor_free_uri(document_raptor_uri); - - return machine; -} - - -} // namespace Machina - diff --git a/src/Machine.cpp b/src/Machine.cpp deleted file mode 100644 index 3cc4ed4..0000000 --- a/src/Machine.cpp +++ /dev/null @@ -1,221 +0,0 @@ -/* This file is part of Machina. - * Copyright (C) 2007 Dave Robillard <http://drobilla.net> - * - * Machina is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Machina is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include <algorithm> -#include "Machine.hpp" -#include "Node.hpp" -#include "Edge.hpp" - -namespace Machina { - - -Machine::Machine() - : _is_activated(false) - , _is_finished(false) - , _time(0) -{ -} - - -Machine::~Machine() -{ -} - - -void -Machine::add_node(SharedPtr<Node> node) -{ - assert(!_is_activated); - - _nodes.push_back(node); -} - - -/** Exit all active states and reset time to 0. - */ -void -Machine::reset() -{ - if (!_is_finished) { - for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) { - const SharedPtr<Node> node = (*n); - - if (node->is_active()) - node->exit(_time); - } - } - - _time = 0; - _is_finished = false; -} - - -/** Return the active Node with the earliest exit time. - */ -SharedPtr<Node> -Machine::earliest_node() const -{ - SharedPtr<Node> earliest; - - for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) { - const SharedPtr<Node> node = (*n); - - if (node->is_active()) - if (!earliest || node->exit_time() < earliest->exit_time()) - earliest = node; - } - - return earliest; -} - - -/** Exit an active node at the current _time. - */ -void -Machine::exit_node(const SharedPtr<Node> node) -{ - node->exit(_time); - - // Activate all successors to this node - // (that aren't aready active right now) - for (Node::EdgeList::const_iterator s = node->outgoing_edges().begin(); - s != node->outgoing_edges().end(); ++s) { - SharedPtr<Node> dst = (*s)->dst(); - - if (!dst->is_active()) - dst->enter(_time); - - } -} - - -/** Run the machine for @a nframes frames. - * - * Returns false when the machine has finished running (i.e. there are - * no currently active states). - * - * If this returns false, time() will return the exact time stamp the - * machine actually finished on (so it can be restarted immediately - * with sample accuracy if necessary). - */ -bool -Machine::run(FrameCount nframes) -{ - if (_is_finished) - return false; - - const FrameCount cycle_end = _time + nframes; - - assert(_is_activated); - - //std::cerr << "--------- " << _time << " - " << _time + nframes << std::endl; - - // Initial run, enter all initial states - if (_time == 0) - for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) - if ((*n)->is_initial()) - (*n)->enter(0); - - while (true) { - - SharedPtr<Node> earliest = earliest_node(); - - // No more active states, machine is finished - if (!earliest) { - _is_finished = true; - return false; - - // Earliest active state ends this cycle - } else if (earliest->exit_time() < cycle_end) { - _time = earliest->exit_time(); - exit_node(earliest); - - // Earliest active state ends in the future, done this cycle - } else { - _time = cycle_end; - return true; - } - - } - -#if 0 - while (!done) { - - done = true; - - for (std::vector<Node*>::iterator i = _voices.begin(); - i != _voices.end(); ++i) { - - Node* const n = *i; - - // Active voice which ends within this cycle, transition - if (n && n->is_active() && n->end_time() < cycle_end) { - // Guaranteed to be within this cycle - const FrameCount end_time = std::max(_time, n->end_time()); - n->exit(std::max(_time, n->end_time())); - done = false; - - // Greedily grab one of the successors with the voice already - // on this node so voices follow paths nicely - for (Node::EdgeList::const_iterator s = n->outgoing_edges().begin(); - s != n->outgoing_edges().end(); ++s) { - Node* dst = (*s)->dst(); - if (!dst->is_active()) { - dst->enter(end_time); - *i = dst; - break; - } - } - - latest_event = end_time; - } - - } - - // FIXME: use free voices to claim any 'free successors' - // (when nodes have multiple successors and one gets chosen in the - // greedy bit above) - - // If every voice is on the initial node... - bool is_reset = true; - for (std::vector<Node*>::iterator i = _voices.begin(); - i != _voices.end(); ++i) - if ((*i) != NULL && (*i)->is_active()) - is_reset = false; - - // ... then start - if (is_reset) { - - std::vector<Node*>::iterator n = _voices.begin(); - for (Node::EdgeList::const_iterator s = _initial_node->outgoing_edges().begin(); - s != _initial_node->outgoing_edges().end() && n != _voices.end(); - ++s, ++n) { - (*s)->dst()->enter(latest_event); - done = false; - *n = (*s)->dst(); - } - } - } - _time += nframes; - - return false; -#endif -} - - -} // namespace Machina - diff --git a/src/Node.cpp b/src/Node.cpp deleted file mode 100644 index 5584f84..0000000 --- a/src/Node.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* This file is part of Machina. - * Copyright (C) 2007 Dave Robillard <http://drobilla.net> - * - * Machina is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Machina is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include <cassert> -#include "Node.hpp" -#include "Edge.hpp" - -namespace Machina { - - -Node::Node(FrameCount duration, bool initial) - : _is_initial(initial) - , _is_active(false) - , _enter_time(0) - , _duration(duration) - , _enter_action(NULL) - , _exit_action(NULL) -{ -} - - -void -Node::add_enter_action(Action* action) -{ - assert(!_enter_action); - _enter_action = action; -} - - -void -Node::remove_enter_action(Action* /*action*/) -{ - _enter_action = NULL; -} - - - -void -Node::add_exit_action(Action* action) -{ - assert(!_exit_action); - _exit_action = action; -} - - -void -Node::remove_exit_action(Action* /*action*/) -{ - _exit_action = NULL; -} - - -void -Node::enter(Timestamp time) -{ - _is_active = true; - _enter_time = time; - if (_enter_action) - _enter_action->execute(time); -} - - -void -Node::exit(Timestamp time) -{ - if (_exit_action) - _exit_action->execute(time); - _is_active = false; - _enter_time = 0; -} - - -void -Node::add_outgoing_edge(SharedPtr<Edge> edge) -{ - assert(edge->src().lock().get() == this); - - _outgoing_edges.push_back(edge); -} - - -void -Node::remove_outgoing_edge(SharedPtr<Edge> edge) -{ - _outgoing_edges.remove(edge); -} - - -} // namespace Machina - diff --git a/src/engine/JackDriver.cpp b/src/engine/JackDriver.cpp index 848c3d7..f6f0ea6 100644 --- a/src/engine/JackDriver.cpp +++ b/src/engine/JackDriver.cpp @@ -33,7 +33,7 @@ JackDriver::JackDriver() void JackDriver::attach(const std::string& client_name) { - Raul::JackDriver::attach(client_name); + Raul::JackDriver::attach(client_name, "debug"); if (jack_client()) { _output_port = jack_port_register(jack_client(), @@ -57,6 +57,8 @@ JackDriver::detach() Timestamp JackDriver::stamp_to_offset(Timestamp stamp) { + assert(stamp >= _current_cycle_start); + Timestamp ret = stamp - _current_cycle_start + _current_cycle_offset; assert(ret < _current_cycle_offset + _current_cycle_nframes); return ret; @@ -77,6 +79,11 @@ JackDriver::on_process(jack_nframes_t nframes) bool machine_done = ! _machine->run(_current_cycle_nframes); + if (machine_done && _machine->time() == 0) { + _machine->reset(); + return; + } + if (!machine_done) { _current_cycle_start += _current_cycle_nframes; break; diff --git a/src/engine/Machine.cpp b/src/engine/Machine.cpp index 426ffd3..5cc54ee 100644 --- a/src/engine/Machine.cpp +++ b/src/engine/Machine.cpp @@ -39,8 +39,6 @@ Machine::~Machine() void Machine::add_node(SharedPtr<Node> node) { - assert(!_is_activated); - _nodes.push_back(node); } @@ -118,9 +116,6 @@ Machine::run(FrameCount nframes) if (_is_finished) return false; - if (_nodes.size() == 0) - return true; - const FrameCount cycle_end = _time + nframes; assert(_is_activated); @@ -128,10 +123,19 @@ Machine::run(FrameCount nframes) //std::cerr << "--------- " << _time << " - " << _time + nframes << std::endl; // Initial run, enter all initial states - if (_time == 0) - for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) - if ((*n)->is_initial()) + if (_time == 0) { + bool entered = false; + for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) { + if ((*n)->is_initial()) { (*n)->enter(0); + entered = true; + } + } + if (!entered) { + _is_finished = true; + return false; + } + } while (true) { diff --git a/src/engine/machina/Machine.hpp b/src/engine/machina/Machine.hpp index 2ac739e..5d16a4e 100644 --- a/src/engine/machina/Machine.hpp +++ b/src/engine/machina/Machine.hpp @@ -36,6 +36,8 @@ public: void activate() { _is_activated = true; } void deactivate() { _is_activated = false; } + bool is_finished() { return _is_finished; } + void add_node(SharedPtr<Node> node); // Audio context diff --git a/src/gui/MachinaCanvas.cpp b/src/gui/MachinaCanvas.cpp index 303774f..775ae28 100644 --- a/src/gui/MachinaCanvas.cpp +++ b/src/gui/MachinaCanvas.cpp @@ -17,10 +17,17 @@ //#include "config.h" #include <raul/SharedPtr.h> -#include <flowcanvas/Ellipse.h> +#include "machina/Node.hpp" +#include "machina/Machine.hpp" +#include "machina/Action.hpp" +#include "machina/Edge.hpp" +#include "NodeView.hpp" #include "MachinaCanvas.hpp" #include "MachinaGUI.hpp" +using namespace LibFlowCanvas; + + MachinaCanvas::MachinaCanvas(MachinaGUI* app, int width, int height) : FlowCanvas(width, height), _app(app) @@ -30,31 +37,86 @@ MachinaCanvas::MachinaCanvas(MachinaGUI* app, int width, int height) void -MachinaCanvas::connect(boost::shared_ptr<Connectable>, //item1, - boost::shared_ptr<Connectable>) //item2) +MachinaCanvas::status_message(const string& msg) { -#if 0 - boost::shared_ptr<MachinaPort> p1 = boost::dynamic_pointer_cast<MachinaPort>(port1); - boost::shared_ptr<MachinaPort> p2 = boost::dynamic_pointer_cast<MachinaPort>(port2); - if (!p1 || !p2) + _app->status_message(string("[Canvas] ").append(msg)); +} + + +void +MachinaCanvas::node_clicked(SharedPtr<NodeView> item, GdkEventButton* event) +{ + cerr << "CLICKED: " << item->name() << endl; + + SharedPtr<NodeView> node = PtrCast<NodeView>(item); + if (!node) return; + + SharedPtr<NodeView> last = _last_clicked.lock(); - if (p1->type() == JACK_AUDIO && p2->type() == JACK_AUDIO - || (p1->type() == JACK_MIDI && p2->type() == JACK_MIDI)) - _app->jack_driver()->connect(p1, p2); -#ifdef HAVE_ALSA - else if (p1->type() == ALSA_MIDI && p2->type() == ALSA_MIDI) - _app->alsa_driver()->connect(p1, p2); -#endif - else - status_message("WARNING: Cannot make connection, incompatible port types."); -#endif + if (last) { + connect(last, node); + _last_clicked.reset(); + } else { + _last_clicked = node; + } +} + + +bool +MachinaCanvas::canvas_event(GdkEvent* event) +{ + static int last = 0; + + assert(event); + + if (event->type == GDK_BUTTON_PRESS) { + + const double x = event->button.x; + const double y = event->button.y; + + if (event->button.button == 1) { + string name = string("Note")+(char)(last++ +'0'); + + SharedPtr<Machina::Node> node(new Machina::Node(1024*10, false)); + node->add_enter_action(new Machina::PrintAction(name)); + SharedPtr<NodeView> view(new NodeView(node, shared_from_this(), + name, x, y)); + + //view->signal_clicked.connect(sigc::bind(sigc::mem_fun(this, + // &MachinaCanvas::node_clicked), view)); + view->signal_clicked.connect(sigc::bind<0>(sigc::mem_fun(this, + &MachinaCanvas::node_clicked), view)); + add_item(view); + view->resize(); + view->raise_to_top(); + + _app->machine()->add_node(node); + } + } + + return FlowCanvas::canvas_event(event); } void -MachinaCanvas::disconnect(boost::shared_ptr<Connectable>,// item1, - boost::shared_ptr<Connectable>)// item2) +MachinaCanvas::connect(boost::shared_ptr<NodeView> src, + boost::shared_ptr<NodeView> dst) +{ + boost::shared_ptr<Connection> c(new Connection(shared_from_this(), + src, dst, 0x9999AAFF, true)); + src->add_connection(c); + dst->add_connection(c); + add_connection(c); + + src->node()->add_outgoing_edge(SharedPtr<Machina::Edge>( + new Machina::Edge(src->node(), dst->node()))); +} + + +void +MachinaCanvas::disconnect(boost::shared_ptr<NodeView>,// item1, + boost::shared_ptr<NodeView>)// item2) { #if 0 boost::shared_ptr<MachinaPort> input @@ -90,79 +152,3 @@ MachinaCanvas::disconnect(boost::shared_ptr<Connectable>,// item1, } -void -MachinaCanvas::status_message(const string& msg) -{ - _app->status_message(string("[Canvas] ").append(msg)); -} - - -void -MachinaCanvas::item_selected(SharedPtr<Item> i) -{ - cerr << "SELECTED: " << i->name() << endl; - - SharedPtr<Connectable> item = PtrCast<Connectable>(i); - if (!item) - return; - - SharedPtr<Connectable> last = _last_selected.lock(); - - if (last) { - boost::shared_ptr<Connection> c(new Connection(shared_from_this(), - last, item, 0x9999AAFF, true)); - last->add_connection(c); - item->add_connection(c); - add_connection(c); - i->raise_to_top(); - _last_selected.reset(); - } else { - _last_selected = item; - } -} - - -void -MachinaCanvas::item_clicked(SharedPtr<Item> i, GdkEventButton* event) -{ - cerr << "CLICKED " << event->button << ": " << i->name() << endl; - - //return false; -} - - -bool -MachinaCanvas::canvas_event(GdkEvent* event) -{ - static int last = 0; - - assert(event); - - if (event->type == GDK_BUTTON_PRESS) { - - const double x = event->button.x; - const double y = event->button.y; - - SharedPtr<Item> item; - - if (event->button.button == 1) { - item = SharedPtr<Item>(new Ellipse(shared_from_this(), - string("Note")+(char)(last++ +'0'), x, y, 30, 30, true)); - } else if (event->button.button == 2) { - item = SharedPtr<Item>(new Module(shared_from_this(), - string("Note")+(char)(last++ +'0'), x, y, true)); - } - - if (item) { - item->signal_selected.connect(sigc::bind(sigc::mem_fun(this, - &MachinaCanvas::item_selected), item)); - item->signal_clicked.connect(sigc::bind<0>(sigc::mem_fun(this, - &MachinaCanvas::item_clicked), item)); - add_item(item); - item->resize(); - item->raise_to_top(); - } - } - - return FlowCanvas::canvas_event(event); -} diff --git a/src/gui/MachinaCanvas.hpp b/src/gui/MachinaCanvas.hpp index b06a5d8..6cd5ea0 100644 --- a/src/gui/MachinaCanvas.hpp +++ b/src/gui/MachinaCanvas.hpp @@ -26,30 +26,31 @@ using namespace LibFlowCanvas; class MachinaGUI; +class NodeView; + class MachinaCanvas : public FlowCanvas { public: - MachinaCanvas(MachinaGUI* _app, int width, int height); + MachinaCanvas(MachinaGUI* app, int width, int height); - void connect(boost::shared_ptr<Connectable> port1, - boost::shared_ptr<Connectable> port2); + void connect(SharedPtr<NodeView> port1, + SharedPtr<NodeView> port2); - void disconnect(boost::shared_ptr<Connectable> port1, - boost::shared_ptr<Connectable> port2); + void disconnect(SharedPtr<NodeView> port1, + SharedPtr<NodeView> port2); void status_message(const string& msg); protected: bool canvas_event(GdkEvent* event); - void item_selected(SharedPtr<Item> item); - void item_clicked(SharedPtr<Item> item, GdkEventButton* ev); + void node_clicked(SharedPtr<NodeView> item, GdkEventButton* ev); private: MachinaGUI* _app; - WeakPtr<Connectable> _last_selected; + WeakPtr<NodeView> _last_clicked; }; diff --git a/src/gui/MachinaGUI.hpp b/src/gui/MachinaGUI.hpp index 804bf41..4bcca5a 100644 --- a/src/gui/MachinaGUI.hpp +++ b/src/gui/MachinaGUI.hpp @@ -35,7 +35,8 @@ public: MachinaGUI(SharedPtr<Machina::Machine> machine/*int argc, char** argv*/); ~MachinaGUI(); - boost::shared_ptr<MachinaCanvas> canvas() { return _canvas; } + boost::shared_ptr<MachinaCanvas> canvas() { return _canvas; } + boost::shared_ptr<Machina::Machine> machine() { return _machine; } Gtk::Window* window() { return _main_window; } @@ -68,8 +69,8 @@ protected: bool _refresh; - boost::shared_ptr<MachinaCanvas> _canvas; - boost::shared_ptr<Machina::Machine> _machine; + boost::shared_ptr<MachinaCanvas> _canvas; + boost::shared_ptr<Machina::Machine> _machine; Gtk::Main* _gtk_main; diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 1bdb381..6a9ff3b 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -17,6 +17,8 @@ machina_gui_SOURCES = \ MachinaGUI.hpp \ MachinaGUI.cpp \ MachinaCanvas.hpp \ - MachinaCanvas.cpp + MachinaCanvas.cpp \ + NodeView.hpp \ + NodeView.cpp endif |