aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-02-10 03:39:10 +0000
committerDavid Robillard <d@drobilla.net>2007-02-10 03:39:10 +0000
commitb924ead0db7c09ee50d2d4eee487b844c5fb867b (patch)
tree36fa1a6c879989a111f4fbbaf9a03b7f442b618c /src
parent9f2a520a8f20661385bf6c9f7447aef1227d8696 (diff)
downloadmachina-b924ead0db7c09ee50d2d4eee487b844c5fb867b.tar.gz
machina-b924ead0db7c09ee50d2d4eee487b844c5fb867b.tar.bz2
machina-b924ead0db7c09ee50d2d4eee487b844c5fb867b.zip
Machine GUI talking to Jack engine, running machines made in GUI, etc.
git-svn-id: http://svn.drobilla.net/lad/machina@297 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src')
-rw-r--r--src/JackActions.cpp88
-rw-r--r--src/JackDriver.cpp102
-rw-r--r--src/JackNodeFactory.cpp42
-rw-r--r--src/Loader.cpp221
-rw-r--r--src/Machine.cpp221
-rw-r--r--src/Node.cpp104
-rw-r--r--src/engine/JackDriver.cpp9
-rw-r--r--src/engine/Machine.cpp20
-rw-r--r--src/engine/machina/Machine.hpp2
-rw-r--r--src/gui/MachinaCanvas.cpp176
-rw-r--r--src/gui/MachinaCanvas.hpp17
-rw-r--r--src/gui/MachinaGUI.hpp7
-rw-r--r--src/gui/Makefile.am4
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