aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-12-04 23:03:45 +0000
committerDavid Robillard <d@drobilla.net>2007-12-04 23:03:45 +0000
commit2ab01419f334b834710a41fd26a538df3522cf49 (patch)
treebd1c1f1662797d9ca50f9bd8eddb1b44908d1e37
parent1760218d029892fc9ba3b25e06479cce319f20a0 (diff)
downloadmachina-2ab01419f334b834710a41fd26a538df3522cf49.tar.gz
machina-2ab01419f334b834710a41fd26a538df3522cf49.tar.bz2
machina-2ab01419f334b834710a41fd26a538df3522cf49.zip
Fix stuck notes on stop.
git-svn-id: http://svn.drobilla.net/lad/machina@948 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--src/engine/ActionFactory.cpp10
-rw-r--r--src/engine/JackDriver.cpp37
-rw-r--r--src/engine/Loader.cpp2
-rw-r--r--src/engine/Machine.cpp8
-rw-r--r--src/engine/SMFDriver.cpp4
-rw-r--r--src/engine/machina/Driver.hpp2
-rw-r--r--src/engine/machina/JackDriver.hpp5
-rw-r--r--src/engine/machina/Machine.hpp4
-rw-r--r--src/gui/MachinaGUI.cpp11
9 files changed, 47 insertions, 36 deletions
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<Action>
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<Action>(new MidiAction(2, buf));
+ return SharedPtr<Action>(new MidiAction(3, buf));
}
SharedPtr<Action>
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<Action>(new MidiAction(2, buf));
+ return SharedPtr<Action>(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> 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<Machine>();
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> 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> 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<Raul::MIDISink> sink, const SharedPtr<Node> node)
BeatCount
Machine::run(const Raul::TimeSlice& time)
{
- using namespace std;
- if (_is_finished) {
+ if (_is_finished)
return 0;
- }
const SharedPtr<Raul::MIDISink> 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 <raul/DoubleBuffer.hpp>
#include <raul/StampedChunkRingBuffer.hpp>
#include <raul/Semaphore.hpp>
+#include <raul/Command.hpp>
#include <jack/midiport.h>
#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<double> _bpm;
Raul::DoubleBuffer<double> _quantization;
+ Raul::Command _stop;
+
Raul::TickTime _record_time;
Raul::AtomicInt _recording;
SharedPtr<Recorder> _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<LearnRequest> 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();