From 2ab01419f334b834710a41fd26a538df3522cf49 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 4 Dec 2007 23:03:45 +0000 Subject: Fix stuck notes on stop. git-svn-id: http://svn.drobilla.net/lad/machina@948 a436a847-0d15-0410-975c-d299462d15a1 --- src/engine/ActionFactory.cpp | 10 ++++++---- src/engine/JackDriver.cpp | 37 ++++++++++++++++++++++--------------- src/engine/Loader.cpp | 2 +- src/engine/Machine.cpp | 8 +++----- src/engine/SMFDriver.cpp | 4 ++-- src/engine/machina/Driver.hpp | 2 +- src/engine/machina/JackDriver.hpp | 5 ++++- src/engine/machina/Machine.hpp | 4 ++-- src/gui/MachinaGUI.cpp | 11 ++++++----- 9 files changed, 47 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/engine/ActionFactory.cpp b/src/engine/ActionFactory.cpp index 4b63e92..4ca1a3e 100644 --- a/src/engine/ActionFactory.cpp +++ b/src/engine/ActionFactory.cpp @@ -24,22 +24,24 @@ namespace Machina { SharedPtr ActionFactory::note_on(unsigned char note) { - unsigned char buf[2]; + unsigned char buf[3]; buf[0] = 0x90; buf[1] = note; + buf[2] = 0x40; - return SharedPtr(new MidiAction(2, buf)); + return SharedPtr(new MidiAction(3, buf)); } SharedPtr ActionFactory::note_off(unsigned char note) { - unsigned char buf[2]; + unsigned char buf[3]; buf[0] = 0x80; buf[1] = note; + buf[2] = 0x40; - return SharedPtr(new MidiAction(2, buf)); + return SharedPtr(new MidiAction(3, buf)); } diff --git a/src/engine/JackDriver.cpp b/src/engine/JackDriver.cpp index 37bf20d..3517250 100644 --- a/src/engine/JackDriver.cpp +++ b/src/engine/JackDriver.cpp @@ -23,6 +23,7 @@ #include "jack_compat.h" using namespace Raul; +using namespace std; namespace Machina { @@ -117,8 +118,6 @@ JackDriver::process_input(SharedPtr machine, const TimeSlice& time) assert(time.offset_ticks() == 0); assert(_input_port); - using namespace std; - if (_recording.get()) { const jack_nframes_t nframes = time.length_ticks(); @@ -245,7 +244,7 @@ JackDriver::on_process(jack_nframes_t nframes) if (_last_machine) { assert(!_last_machine.unique()); // Realtime, can't delete _last_machine->set_sink(shared_from_this()); - _last_machine->reset(); // Exit all active states + _last_machine->reset(_last_machine->time()); // Exit all active states _last_machine.reset(); // Cut our reference } _cycle_time.set_start(0); @@ -254,14 +253,17 @@ JackDriver::on_process(jack_nframes_t nframes) if (_recording.get()) _record_time += nframes; - + if (!machine) return; + if (_stop.pending()) + machine->reset(_cycle_time.start_beats()); + process_input(machine, _cycle_time); if (machine->is_empty() || !machine->is_activated()) - return; + goto end; while (true) { @@ -270,16 +272,16 @@ JackDriver::on_process(jack_nframes_t nframes) // Machine didn't run at all (empty, or no initial states) if (run_dur_beats == 0) { - machine->reset(); // Try again next cycle + machine->reset(machine->time()); // Try again next cycle _cycle_time.set_start(0); - return; + goto end; // Machine ran for portion of cycle (finished) } else if (run_dur_ticks < _cycle_time.length_ticks()) { const TickCount finish_offset = _cycle_time.offset_ticks() + run_dur_ticks; assert(finish_offset < nframes); - machine->reset(); + machine->reset(machine->time()); _cycle_time.set_start(0); _cycle_time.set_length(nframes - finish_offset); @@ -288,7 +290,7 @@ JackDriver::on_process(jack_nframes_t nframes) // Machine ran for entire cycle } else { if (machine->is_finished()) { - machine->reset(); + machine->reset(machine->time()); _cycle_time.set_start(0); } else { _cycle_time.set_start( @@ -302,17 +304,22 @@ 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; + +end: + if (_stop.pending()) { + _cycle_time.set_start(0); + _stop.finish(); + } } void -JackDriver::reset() +JackDriver::stop() { - /* FIXME: This should signal the audio thread and wait for it - * to exit all active states to resolve stuck notes, then reset. */ - _machine->deactivate(); - _machine->reset(); - _cycle_time.set_start(0); + if (recording()) + finish_record(); + + _stop(); // waits } diff --git a/src/engine/Loader.cpp b/src/engine/Loader.cpp index 0e3d799..27b95fd 100644 --- a/src/engine/Loader.cpp +++ b/src/engine/Loader.cpp @@ -181,7 +181,7 @@ Loader::load(const Glib::ustring& uri) } if (machine && machine->nodes().size() > 0) { - machine->reset(); + machine->reset(machine->time()); return machine; } else { return SharedPtr(); diff --git a/src/engine/Machine.cpp b/src/engine/Machine.cpp index 11d894c..7f668ef 100644 --- a/src/engine/Machine.cpp +++ b/src/engine/Machine.cpp @@ -76,7 +76,7 @@ Machine::remove_node(SharedPtr node) /** Exit all active states and reset time to 0. */ void -Machine::reset() +Machine::reset(Raul::BeatTime time) { for (size_t i=0; i < MAX_ACTIVE_NODES; ++i) { _active_nodes[i].reset(); @@ -87,7 +87,7 @@ Machine::reset() const SharedPtr node = (*n); if (node->is_active()) - node->exit(_sink.lock(), _time); + node->exit(_sink.lock(), time); assert(! node->is_active()); } @@ -216,10 +216,8 @@ Machine::exit_node(SharedPtr sink, const SharedPtr node) BeatCount Machine::run(const Raul::TimeSlice& time) { - using namespace std; - if (_is_finished) { + if (_is_finished) return 0; - } const SharedPtr sink = _sink.lock(); diff --git a/src/engine/SMFDriver.cpp b/src/engine/SMFDriver.cpp index e885e4b..85aa8ab 100644 --- a/src/engine/SMFDriver.cpp +++ b/src/engine/SMFDriver.cpp @@ -62,7 +62,7 @@ SMFDriver::learn(const string& filename, unsigned track, double q, Raul::BeatTim else learn_track(builder, reader, track, q, max_duration); - m->reset(); + m->reset(m->time()); if (m->nodes().size() > 1) return m; @@ -92,7 +92,7 @@ SMFDriver::learn(const string& filename, double q, Raul::BeatTime max_duration) learn_track(builder, reader, t, q, max_duration); } - m->reset(); + m->reset(m->time()); if (m->nodes().size() > 1) return m; diff --git a/src/engine/machina/Driver.hpp b/src/engine/machina/Driver.hpp index 098cb0a..e497356 100644 --- a/src/engine/machina/Driver.hpp +++ b/src/engine/machina/Driver.hpp @@ -39,7 +39,7 @@ public: virtual void activate() {} virtual void deactivate() {} - virtual void reset() {} + virtual void stop() {} virtual bool recording() { return false; } virtual void start_record() {} diff --git a/src/engine/machina/JackDriver.hpp b/src/engine/machina/JackDriver.hpp index 72f8dfd..017d867 100644 --- a/src/engine/machina/JackDriver.hpp +++ b/src/engine/machina/JackDriver.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "Machine.hpp" #include "Driver.hpp" @@ -62,7 +63,7 @@ public: void set_bpm(double bpm) { _bpm.set(bpm); } void set_quantization(double quantization) { _quantization.set(quantization); } - void reset(); + void stop(); bool recording() { return _recording.get(); } void start_record(); @@ -85,6 +86,8 @@ private: Raul::DoubleBuffer _bpm; Raul::DoubleBuffer _quantization; + Raul::Command _stop; + Raul::TickTime _record_time; Raul::AtomicInt _recording; SharedPtr _recorder; diff --git a/src/engine/machina/Machine.hpp b/src/engine/machina/Machine.hpp index c6f8796..c63537d 100644 --- a/src/engine/machina/Machine.hpp +++ b/src/engine/machina/Machine.hpp @@ -50,11 +50,11 @@ public: void write_state(Redland::Model& model); // Audio context - void reset(); + void reset(Raul::BeatTime time); BeatCount run(const Raul::TimeSlice& time); // Any context - Raul::BeatTime time() { return _time; } + inline Raul::BeatTime time() const { return _time; } SharedPtr pending_learn() { return _pending_learn; } void clear_pending_learn() { _pending_learn.reset(); } diff --git a/src/gui/MachinaGUI.cpp b/src/gui/MachinaGUI.cpp index f8939b4..2e383ec 100644 --- a/src/gui/MachinaGUI.cpp +++ b/src/gui/MachinaGUI.cpp @@ -376,7 +376,7 @@ MachinaGUI::menu_import_midi() if (machine) { dialog.hide(); machine->activate(); - machine->reset(); + machine->reset(machine->time()); _canvas->build(machine); _engine->driver()->set_machine(machine); } else { @@ -406,7 +406,7 @@ MachinaGUI::menu_export_midi() file_driver->writer()->start(dialog.get_filename()); file_driver->run(m, 32); // TODO: solve halting problem m->set_sink(_engine->driver()); - m->reset(); + m->reset(m->time()); file_driver->writer()->finish(); _engine->driver()->activate(); } @@ -492,10 +492,11 @@ void MachinaGUI::stop_clicked() { if (_engine->driver()->recording()) { - _engine->driver()->finish_record(); + _engine->driver()->stop(); + _canvas->build(_engine->machine()); + update_toolbar(); } else { - _engine->machine()->deactivate(); - _engine->driver()->reset(); + _engine->driver()->stop(); } update_toolbar(); -- cgit v1.2.1