summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-07-28 07:09:21 +0000
committerDavid Robillard <d@drobilla.net>2007-07-28 07:09:21 +0000
commit6e167cb1a835cb0b44990cc4c2b2a47db9dd2b9e (patch)
treee31d6aac9c2ca21a46f18a24822b47c2003aee4c /libs
parent71452634a711cfeae4cf7eb9fbe7667210a071f1 (diff)
Playback from MIDI model, playback of clicked-in events.
Note the diskstream chunk size affects reading of clicked-in, so you may need to seek away and back again to have new events read (this will be fixed). git-svn-id: svn://localhost/ardour2/trunk@2183 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/midi_buffer.h2
-rw-r--r--libs/ardour/ardour/midi_diskstream.h3
-rw-r--r--libs/ardour/ardour/midi_model.h49
-rw-r--r--libs/ardour/ardour/midi_ring_buffer.h27
-rw-r--r--libs/ardour/ardour/midi_source.h6
-rw-r--r--libs/ardour/ardour/midi_track.h2
-rw-r--r--libs/ardour/ardour/source.h1
-rw-r--r--libs/ardour/ardour/types.h4
-rw-r--r--libs/ardour/audio_diskstream.cc2
-rw-r--r--libs/ardour/enums.cc4
-rw-r--r--libs/ardour/midi_buffer.cc5
-rw-r--r--libs/ardour/midi_diskstream.cc12
-rw-r--r--libs/ardour/midi_model.cc171
-rw-r--r--libs/ardour/midi_source.cc31
-rw-r--r--libs/ardour/midi_track.cc26
-rw-r--r--libs/ardour/smf_source.cc10
16 files changed, 284 insertions, 71 deletions
diff --git a/libs/ardour/ardour/midi_buffer.h b/libs/ardour/ardour/midi_buffer.h
index 17feea6ff1..2ba6a0990b 100644
--- a/libs/ardour/ardour/midi_buffer.h
+++ b/libs/ardour/ardour/midi_buffer.h
@@ -81,7 +81,7 @@ private:
const MidiEvent& operator[](size_t i) const { assert(i < _size); return _events[i]; }
MidiEvent& operator[](size_t i) { assert(i < _size); return _events[i]; }
- // FIXME: Jack needs to tell us this
+ // FIXME: Eliminate this
static const size_t MAX_EVENT_SIZE = 4; // bytes
/* We use _size as "number of events", so the size of _data is
diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h
index be329b4704..53c7a7e22c 100644
--- a/libs/ardour/ardour/midi_diskstream.h
+++ b/libs/ardour/ardour/midi_diskstream.h
@@ -88,6 +88,8 @@ class MidiDiskstream : public Diskstream
boost::shared_ptr<SMFSource> write_source () { return _write_source; }
int set_destructive (bool yn); // doom!
+
+ void set_note_mode (NoteMode m);
protected:
friend class Session;
@@ -154,6 +156,7 @@ class MidiDiskstream : public Diskstream
boost::shared_ptr<SMFSource> _write_source;
RingBufferNPT<CaptureTransition>* _capture_transition_buf;
nframes_t _last_flush_frame;
+ NoteMode _note_mode;
};
}; /* namespace ARDOUR */
diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h
index 49ef21b26f..a2e2275157 100644
--- a/libs/ardour/ardour/midi_model.h
+++ b/libs/ardour/ardour/midi_model.h
@@ -25,6 +25,7 @@
#include <pbd/command.h>
#include <ardour/types.h>
#include <ardour/midi_buffer.h>
+#include <ardour/midi_ring_buffer.h>
namespace ARDOUR {
@@ -40,25 +41,46 @@ class Session;
class MidiModel : public boost::noncopyable {
public:
struct Note {
- Note(double s=0, double d=0, uint8_t n=0, uint8_t v=0)
- : start(s), duration(d), note(n), velocity(v) {}
+ Note(double time=0, double dur=0, uint8_t note=0, uint8_t vel=0x40);
+ Note(const Note& copy);
inline bool operator==(const Note& other)
- { return start == other.start && note == other.note; }
+ { return time() == other.time() && note() == other.note(); }
- double start;
- double duration;
- uint8_t note;
- uint8_t velocity;
+ inline double time() const { return _on_event.time; }
+ inline double end_time() const { return _off_event.time; }
+ inline uint8_t note() const { return _on_event.note(); }
+ inline uint8_t velocity() const { return _on_event.velocity(); }
+ inline double duration() const { return _off_event.time - _on_event.time; }
+
+ inline void set_duration(double d) { _off_event.time = _on_event.time + d; }
+
+ inline MidiEvent& on_event() { return _on_event; }
+ inline MidiEvent& off_event() { return _off_event; }
+
+ inline const MidiEvent& on_event() const { return _on_event; }
+ inline const MidiEvent& off_event() const { return _off_event; }
+
+ private:
+ MidiEvent _on_event;
+ MidiEvent _off_event;
+ Byte _on_event_buffer[3];
+ Byte _off_event_buffer[3];
};
MidiModel(Session& s, size_t size=0);
void clear() { _notes.clear(); }
+ NoteMode note_mode() const { return _note_mode; }
+ void set_note_mode(NoteMode mode) { _note_mode = mode; }
+
void start_write();
+ bool currently_writing() const { return _writing; }
void end_write(bool delete_stuck=false);
+ size_t read (MidiRingBuffer& dst, nframes_t start, nframes_t nframes, nframes_t stamp_offset) const;
+
/** Resizes vector if necessary (NOT realtime safe) */
void append(const MidiBuffer& data);
@@ -72,9 +94,16 @@ public:
typedef std::vector<Note> Notes;
inline static bool note_time_comparator (const Note& a, const Note& b) {
- return a.start < b.start;
+ return a.time() < b.time();
}
+ struct LaterNoteEndComparator {
+ typedef const Note* value_type;
+ inline bool operator()(const Note* const a, const Note* const b) {
+ return a->end_time() > b->end_time();
+ }
+ };
+
inline Notes& notes() { return _notes; }
inline const Notes& notes() const { return _notes; }
@@ -115,10 +144,12 @@ private:
Session& _session;
- Notes _notes;
+ Notes _notes;
+ NoteMode _note_mode;
typedef std::vector<size_t> WriteNotes;
WriteNotes _write_notes;
+ bool _writing;
MidiEditCommand* _command; ///< In-progress command
};
diff --git a/libs/ardour/ardour/midi_ring_buffer.h b/libs/ardour/ardour/midi_ring_buffer.h
index 3effb96664..6c57c78c3c 100644
--- a/libs/ardour/ardour/midi_ring_buffer.h
+++ b/libs/ardour/ardour/midi_ring_buffer.h
@@ -19,6 +19,7 @@
#ifndef __ardour_midi_ring_buffer_h__
#define __ardour_midi_ring_buffer_h__
+#include <iostream>
#include <algorithm>
#include <ardour/types.h>
#include <ardour/buffer.h>
@@ -252,6 +253,9 @@ MidiRingBuffer::read(double* time, size_t* size, Byte* buf)
inline size_t
MidiRingBuffer::write(double time, size_t size, const Byte* buf)
{
+ //printf("MRB - write %#X %d %d with time %lf\n",
+ // buf[0], buf[1], buf[2], time);
+
assert(size > 0);
if (write_space() < (sizeof(double) + sizeof(size_t) + size)) {
@@ -280,6 +284,8 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
size_t count = 0;
+ //printf("MRB - read %u .. %u + %u\n", start, end, offset);
+
while (read_space() > sizeof(double) + sizeof(size_t)) {
full_peek(sizeof(double), (Byte*)&ev.time);
@@ -292,30 +298,25 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
success = MidiRingBufferBase<Byte>::full_read(sizeof(size_t), (Byte*)&ev.size);
if (!success) {
- cerr << "MRB: READ ERROR (time/size)" << endl;
+ std::cerr << "MRB: READ ERROR (time/size)" << std::endl;
continue;
}
if (ev.time >= start) {
+ ev.time -= start;
Byte* write_loc = dst.reserve(ev.time, ev.size);
success = MidiRingBufferBase<Byte>::full_read(ev.size, write_loc);
- if (!success)
- cerr << "MRB: READ ERROR (data)" << endl;
+ if (success) {
+ ++count;
+ //printf("MRB - read event at time %lf\n", ev.time);
+ } else {
+ std::cerr << "MRB: READ ERROR (data)" << std::endl;
+ }
- //printf("MRB - read %#X %d %d with time %u at index %zu\n",
- // ev.buffer[0], ev.buffer[1], ev.buffer[2], ev.time,
- // priv_read_ptr);
- //
} else {
printf("MRB - SKIPPING EVENT (with time %f)\n", ev.time);
- break;
}
-
- ++count;
-
- assert(ev.time <= end);
- ev.time -= start;
}
//printf("(R) read space: %zu\n", read_space());
diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h
index d95d0fd75a..5393f07157 100644
--- a/libs/ardour/ardour/midi_source.h
+++ b/libs/ardour/ardour/midi_source.h
@@ -53,7 +53,9 @@ class MidiSource : public Source
virtual nframes_t write (MidiRingBuffer& src, nframes_t cnt);
virtual void mark_for_remove() = 0;
- virtual void mark_streaming_write_completed () {}
+ virtual void mark_streaming_midi_write_started (NoteMode mode);
+ virtual void mark_streaming_write_started ();
+ virtual void mark_streaming_write_completed ();
string captured_for() const { return _captured_for; }
void set_captured_for (string str) { _captured_for = str; }
@@ -72,6 +74,8 @@ class MidiSource : public Source
virtual void load_model(bool lock=true, bool force_reload=false) = 0;
virtual void destroy_model() = 0;
+ virtual bool model_loaded() const { return _model_loaded; }
+
MidiModel* model() { return _model; }
protected:
diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h
index bb55454d3b..c9ead65d49 100644
--- a/libs/ardour/ardour/midi_track.h
+++ b/libs/ardour/ardour/midi_track.h
@@ -84,7 +84,7 @@ public:
};
NoteMode note_mode() const { return _note_mode; }
- void set_note_mode (NoteMode m) { _note_mode = m; }
+ void set_note_mode (NoteMode m);
protected:
diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h
index 029469f491..e1843df75c 100644
--- a/libs/ardour/ardour/source.h
+++ b/libs/ardour/ardour/source.h
@@ -55,6 +55,7 @@ class Source : public SessionObject
virtual nframes_t natural_position() const { return 0; }
virtual void mark_for_remove() = 0;
+ virtual void mark_streaming_write_started () {}
virtual void mark_streaming_write_completed () = 0;
XMLNode& get_state ();
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index 9edeffb120..e13bd09d83 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -129,8 +129,8 @@ namespace ARDOUR {
};
enum NoteMode {
- Note,
- Percussion
+ Sustained,
+ Percussive
};
struct BBT_Time {
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index 14eef2961b..135aa4747f 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -1794,11 +1794,13 @@ AudioDiskstream::engage_record_enable ()
(*chan)->source->ensure_monitor_input (!(Config->get_auto_input() && rolling));
}
capturing_sources.push_back ((*chan)->write_source);
+ (*chan)->write_source->mark_streaming_write_started ();
}
} else {
for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
capturing_sources.push_back ((*chan)->write_source);
+ (*chan)->write_source->mark_streaming_write_started ();
}
}
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 91fbda89c5..f2d2e92169 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -136,8 +136,8 @@ setup_enum_writer ()
REGISTER_ENUM (Destructive);
REGISTER (_TrackMode);
- REGISTER_ENUM (Note);
- REGISTER_ENUM (Percussion);
+ REGISTER_ENUM (Sustained);
+ REGISTER_ENUM (Percussive);
REGISTER (_NoteMode);
REGISTER_ENUM (MeterFalloffOff);
diff --git a/libs/ardour/midi_buffer.cc b/libs/ardour/midi_buffer.cc
index 5376886a5d..5b7c789ba0 100644
--- a/libs/ardour/midi_buffer.cc
+++ b/libs/ardour/midi_buffer.cc
@@ -91,7 +91,10 @@ MidiBuffer::read_from(const Buffer& src, nframes_t nframes, nframes_t offset)
for (size_t i=0; i < src.size(); ++i) {
const MidiEvent& ev = msrc[i];
if (ev.time >= offset && ev.time < offset+nframes) {
+ //cerr << "MidiBuffer::read_from got event, " << ev.time << endl;
push_back(ev);
+ } else {
+ //cerr << "MidiBuffer event out of range, " << ev.time << endl;
}
}
@@ -166,7 +169,7 @@ MidiBuffer::push_back(const jack_midi_event_t& ev)
Byte*
MidiBuffer::reserve(double time, size_t size)
{
- assert(size < MAX_EVENT_SIZE);
+ assert(size <= MAX_EVENT_SIZE);
if (_size == _capacity)
return NULL;
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index 691335de93..c5711a8295 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -68,6 +68,7 @@ MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::F
, _source_port(0)
, _capture_transition_buf(0)
, _last_flush_frame(0)
+ , _note_mode(Sustained)
{
/* prevent any write sources from being created */
@@ -92,6 +93,7 @@ MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node)
, _source_port(0)
, _capture_transition_buf(0)
, _last_flush_frame(0)
+ , _note_mode(Sustained)
{
in_set_state = true;
init (Recordable);
@@ -305,6 +307,14 @@ MidiDiskstream::set_destructive (bool yn)
assert( ! yn);
return -1;
}
+
+void
+MidiDiskstream::set_note_mode (NoteMode m)
+{
+ _note_mode = m;
+ if (_write_source && _write_source->model())
+ _write_source->model()->set_note_mode(m);
+}
void
MidiDiskstream::check_record_status (nframes_t transport_frame, nframes_t nframes, bool can_record)
@@ -1212,6 +1222,8 @@ MidiDiskstream::engage_record_enable ()
_source_port->request_monitor_input (!(Config->get_auto_input() && rolling));
}
+ _write_source->mark_streaming_midi_write_started (_note_mode);
+
RecordEnableChanged (); /* EMIT SIGNAL */
}
diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc
index 1c6990e84d..b1a87551b1 100644
--- a/libs/ardour/midi_model.cc
+++ b/libs/ardour/midi_model.cc
@@ -19,6 +19,8 @@
*/
#include <iostream>
+#include <queue>
+#include <pbd/enumwriter.h>
#include <ardour/midi_model.h>
#include <ardour/midi_events.h>
#include <ardour/types.h>
@@ -27,41 +29,155 @@
using namespace std;
using namespace ARDOUR;
+// Note
+
+MidiModel::Note::Note(double t, double d, uint8_t n, uint8_t v)
+{
+ _on_event.time = t;
+ _on_event.buffer = _on_event_buffer;
+ _on_event.size = 3;
+ _on_event.buffer[0] = MIDI_CMD_NOTE_ON;
+ _on_event.buffer[1] = n;
+ _on_event.buffer[2] = v;
+
+ _off_event.time = t + d;
+ _off_event.buffer = _off_event_buffer;
+ _off_event.size = 3;
+ _off_event.buffer[0] = MIDI_CMD_NOTE_OFF;
+ _off_event.buffer[1] = n;
+ _off_event.buffer[2] = 0x40;
+
+ assert(time() == t);
+ assert(duration() == d);
+ assert(note() == n);
+ assert(velocity() == v);
+}
+
+
+MidiModel::Note::Note(const Note& copy)
+ : _on_event(copy._on_event)
+ , _off_event(copy._off_event)
+{
+ memcpy(_on_event_buffer, copy._on_event_buffer, 3);
+ memcpy(_off_event_buffer, copy._off_event_buffer, 3);
+ _on_event.buffer = _on_event_buffer;
+ _off_event.buffer = _off_event_buffer;
+}
+
+
+// MidiModel
MidiModel::MidiModel(Session& s, size_t size)
: _session(s)
, _notes(size)
+ , _note_mode(Sustained)
+ , _writing(false)
, _command(NULL)
{
}
+/** Read events in frame range \a start .. \a start+cnt into \a dst,
+ * adding \a stamp_offset to each event's timestamp.
+ * \return number of events written to \a dst
+ */
+size_t
+MidiModel::read (MidiRingBuffer& dst, nframes_t start, nframes_t nframes, nframes_t stamp_offset) const
+{
+ size_t read_events = 0;
+
+ //cerr << "MM READ " << start << " .. " << nframes << endl;
+
+ /* FIXME: cache last lookup value to avoid the search */
+
+ if (_note_mode == Sustained) {
+ LaterNoteEndComparator cmp;
+ priority_queue<const Note*,vector<const Note*>,LaterNoteEndComparator> active_notes(cmp);
+
+ /* FIXME: cache last lookup value to avoid the search */
+ for (Notes::const_iterator n = _notes.begin(); n != _notes.end(); ++n) {
+
+ //cerr << "MM ON " << n->time() << endl;
+
+ if (n->time() >= start + nframes)
+ break;
+
+ while ( ! active_notes.empty() ) {
+ const Note* const earliest_off = active_notes.top();
+ const MidiEvent& ev = earliest_off->off_event();
+ if (ev.time < start + nframes && ev.time <= n->time()) {
+ dst.write(ev.time + stamp_offset, ev.size, ev.buffer);
+ active_notes.pop();
+ ++read_events;
+ } else {
+ break;
+ }
+ }
+
+ // Note on
+ if (n->time() >= start) {
+ const MidiEvent& ev = n->on_event();
+ dst.write(ev.time + stamp_offset, ev.size, ev.buffer);
+ active_notes.push(&(*n));
+ ++read_events;
+ }
+
+ }
+
+ // Percussive
+ } else {
+ for (Notes::const_iterator n = _notes.begin(); n != _notes.end(); ++n) {
+ // Note on
+ if (n->time() >= start) {
+ if (n->time() < start + nframes) {
+ const MidiEvent& ev = n->on_event();
+ dst.write(ev.time + stamp_offset, ev.size, ev.buffer);
+ ++read_events;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ return read_events;
+}
+
+
/** Begin a write of events to the model.
*
- * As note on and off events are written, complete notes with duration are
- * constructed
+ * If \a mode is Sustained, complete notes with duration are constructed as note
+ * on/off events are received. Otherwise (Percussive), only note on events are
+ * stored; note off events are discarded entirely and all contained notes will
+ * have duration 0.
*/
void
MidiModel::start_write()
{
+ //cerr << "MM START WRITE, MODE = " << enum_2_string(_note_mode) << endl;
_write_notes.clear();
+ _writing = true;
}
/** Finish a write of events to the model.
*
- * If \a delete_stuck is true, note on events that were never resolved with
- * a corresonding note off will be deleted. Otherwise they will remain as
- * notes with duration 0.
+ * If \a delete_stuck is true and the current mode is Sustained, note on events
+ * that were never resolved with a corresonding note off will be deleted.
+ * Otherwise they will remain as notes with duration 0.
*/
void
MidiModel::end_write(bool delete_stuck)
{
- if (delete_stuck) {
+ assert(_writing);
+
+ //cerr << "MM END WRITE\n";
+
+ if (_note_mode == Sustained && delete_stuck) {
for (Notes::iterator n = _notes.begin(); n != _notes.end() ; ) {
- if (n->duration == 0) {
- cerr << "WARNING: Stuck note lost: " << n->note << endl;
+ if (n->duration() == 0) {
+ cerr << "WARNING: Stuck note lost: " << n->note() << endl;
n = _notes.erase(n);
} else {
++n;
@@ -70,6 +186,7 @@ MidiModel::end_write(bool delete_stuck)
}
_write_notes.clear();
+ _writing = false;
}
@@ -84,10 +201,12 @@ MidiModel::end_write(bool delete_stuck)
void
MidiModel::append(const MidiBuffer& buf)
{
+ assert(_writing);
+
for (MidiBuffer::const_iterator i = buf.begin(); i != buf.end(); ++i) {
const MidiEvent& ev = *i;
- assert(_notes.empty() || ev.time >= _notes.back().start);
+ assert(_notes.empty() || ev.time >= _notes.back().time());
if (ev.type() == MIDI_CMD_NOTE_ON)
append_note_on(ev.time, ev.note(), ev.velocity());
@@ -106,7 +225,8 @@ MidiModel::append(const MidiBuffer& buf)
void
MidiModel::append(double time, size_t size, const Byte* buf)
{
- assert(_notes.empty() || time >= _notes.back().start);
+ assert(_notes.empty() || time >= _notes.back().time());
+ assert(_writing);
if ((buf[0] & 0xF0) == MIDI_CMD_NOTE_ON)
append_note_on(time, buf[1], buf[2]);
@@ -118,28 +238,41 @@ MidiModel::append(double time, size_t size, const Byte* buf)
void
MidiModel::append_note_on(double time, uint8_t note_num, uint8_t velocity)
{
+ assert(_writing);
_notes.push_back(Note(time, 0, note_num, velocity));
- _write_notes.push_back(_notes.size() - 1);
+ if (_note_mode == Sustained) {
+ //cerr << "MM Appending note on " << (unsigned)(uint8_t)note_num << endl;
+ _write_notes.push_back(_notes.size() - 1);
+ } else {
+ //cerr << "MM NOT appending note on" << endl;
+ }
}
void
MidiModel::append_note_off(double time, uint8_t note_num)
{
- /* _write_notes (active notes) is presumably small enough for linear
- * search to be a good idea. maybe not with instruments (percussion)
- * that don't send note off at all though.... FIXME? */
+ assert(_writing);
+ if (_note_mode == Percussive) {
+ //cerr << "MM Ignoring note off (percussive mode)" << endl;
+ return;
+ } else {
+ //cerr << "MM Attempting to resolve note off " << (unsigned)(uint8_t)note_num << endl;
+ }
+ /* FIXME: make _write_notes fixed size (127 noted) for speed */
+
/* FIXME: note off velocity for that one guy out there who actually has
* keys that send it */
for (WriteNotes::iterator n = _write_notes.begin(); n != _write_notes.end(); ++n) {
Note& note = _notes[*n];
- if (note.note == note_num) {
- assert(time > note.start);
- note.duration = time - note.start;
+ //cerr << (unsigned)(uint8_t)note.note() << " ? " << (unsigned)note_num << endl;
+ if (note.note() == note_num) {
+ assert(time > note.time());
+ note.set_duration(time - note.time());
_write_notes.erase(n);
- //cerr << "MidiModel resolved note, duration: " << note.duration << endl;
+ //cerr << "MidiModel resolved note, duration: " << note.duration() << endl;
break;
}
}
@@ -149,6 +282,7 @@ MidiModel::append_note_off(double time, uint8_t note_num)
void
MidiModel::add_note(const Note& note)
{
+ // FIXME: take source lock
Notes::iterator i = upper_bound(_notes.begin(), _notes.end(), note, note_time_comparator);
_notes.insert(i, note);
if (_command)
@@ -159,6 +293,7 @@ MidiModel::add_note(const Note& note)
void
MidiModel::remove_note(const Note& note)
{
+ // FIXME: take source lock
Notes::iterator n = find(_notes.begin(), _notes.end(), note);
if (n != _notes.end())
_notes.erase(n);
diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc
index f2a3121be2..238bf4f481 100644
--- a/libs/ardour/midi_source.cc
+++ b/libs/ardour/midi_source.cc
@@ -99,7 +99,13 @@ nframes_t
MidiSource::read (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset) const
{
Glib::Mutex::Lock lm (_lock);
- return read_unlocked (dst, start, cnt, stamp_offset);
+ if (_model_loaded && _model) {
+ /*const size_t n_events = */_model->read(dst, start, cnt, stamp_offset);
+ //cout << "Read " << n_events << " events from model." << endl;
+ return cnt;
+ } else {
+ return read_unlocked (dst, start, cnt, stamp_offset);
+ }
}
nframes_t
@@ -119,3 +125,26 @@ MidiSource::file_changed (string path)
return ( !e1 );
}
+void
+MidiSource::mark_streaming_midi_write_started (NoteMode mode)
+{
+ if (_model) {
+ _model->set_note_mode(mode);
+ _model->start_write();
+ }
+}
+
+void
+MidiSource::mark_streaming_write_started ()
+{
+ if (_model)
+ _model->start_write();
+}
+
+void
+MidiSource::mark_streaming_write_completed ()
+{
+ if (_model)
+ _model->end_write(false); // FIXME: param?
+}
+
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 3d7c429075..55d195fab0 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -167,7 +167,7 @@ MidiTrack::_set_state (const XMLNode& node, bool call_base)
if ((prop = node.property (X_("note-mode"))) != 0) {
_note_mode = NoteMode (string_2_enum (prop->value(), _note_mode));
} else {
- _note_mode = Note;
+ _note_mode = Sustained;
}
if ((prop = node.property ("diskstream-id")) == 0) {
@@ -569,7 +569,6 @@ MidiTrack::process_output_buffers (BufferSet& bufs,
MidiBuffer& output_buf = bufs.get_midi(0);
write_controller_messages(output_buf, start_frame, end_frame, nframes, offset);
-
deliver_output(bufs, start_frame, end_frame, nframes, offset);
}
}
@@ -685,26 +684,13 @@ MidiTrack::unfreeze ()
_freeze_record.state = UnFrozen;
FreezeChange (); /* EMIT SIGNAL */
}
-#if 0
-int
-MidiTrack::set_mode (TrackMode m)
-{
- assert(_diskstream);
-
- if (m != _mode) {
-
- if (_diskstream->set_destructive (m == Destructive)) {
- return -1;
- }
- _mode = m;
-
- TrackModeChanged (); /* EMIT SIGNAL */
- }
-
- return 0;
+void
+MidiTrack::set_note_mode (NoteMode m)
+{
+ _note_mode = m;
+ midi_diskstream()->set_note_mode(m);
}
-#endif
/** \return true on success, false on failure (no buffer space left)
*/
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index 08ec1d87a8..eac782853f 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -408,7 +408,12 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
const nframes_t oldlen = _length;
update_length(oldlen, cnt);
- _model->append(buf);
+ if (_model) {
+ if ( ! _model->currently_writing()) {
+ _model->start_write();
+ }
+ _model->append(buf);
+ }
ViewDataRangeReady (buf_ptr, oldlen, cnt); /* EMIT SIGNAL */
@@ -463,6 +468,8 @@ SMFSource::mark_for_remove ()
void
SMFSource::mark_streaming_write_completed ()
{
+ MidiSource::mark_streaming_write_completed();
+
if (!writable()) {
return;
}
@@ -828,7 +835,6 @@ SMFSource::load_model(bool lock, bool force_reload)
const double ev_time = (double)(time * frames_per_beat / (double)_ppqn); // in frames
if (ret > 0) { // didn't skip (meta) event
- //cerr << "ADDING EVENT TO MODEL: " << ev.time << endl;
_model->append(ev_time, ev.size, ev.buffer);
}