summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2008-03-18 03:42:32 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2008-03-18 03:42:32 +0000
commiteb4a1fdbb8fec1f8aa5dfe33f882064e85792a84 (patch)
treeb97aadaf2a8593e33ceaf1e4da78ab39d2608702 /libs
parentd69f4e9e3dde0e400c80bca37f7bfcc555fbbf1b (diff)
refactor JACK MIDI port to allow writing from a non-process() thread, and move ARDOUR::MidiEvent into MIDI namespace along with midi_events.h header
git-svn-id: svn://localhost/ardour2/branches/3.0@3155 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/midi_buffer.h14
-rw-r--r--libs/ardour/ardour/midi_model.h10
-rw-r--r--libs/ardour/ardour/midi_ring_buffer.h2
-rw-r--r--libs/ardour/ardour/midi_source.h2
-rw-r--r--libs/ardour/ardour/midi_util.h2
-rw-r--r--libs/ardour/ardour/note.h16
-rw-r--r--libs/ardour/ardour/smf_source.h2
-rw-r--r--libs/ardour/audioengine.cc3
-rw-r--r--libs/ardour/globals.cc15
-rw-r--r--libs/ardour/import.cc2
-rw-r--r--libs/ardour/jack_midi_port.cc2
-rw-r--r--libs/ardour/meter.cc2
-rw-r--r--libs/ardour/midi_buffer.cc14
-rw-r--r--libs/ardour/midi_diskstream.cc2
-rw-r--r--libs/ardour/midi_model.cc17
-rw-r--r--libs/ardour/midi_stretch.cc4
-rw-r--r--libs/ardour/midi_track.cc5
-rw-r--r--libs/ardour/smf_reader.cc3
-rw-r--r--libs/ardour/smf_source.cc6
-rw-r--r--libs/midi++2/SConscript8
-rw-r--r--libs/midi++2/jack_midiport.cc95
-rw-r--r--libs/midi++2/midi++/event.h (renamed from libs/ardour/ardour/midi_event.h)76
-rw-r--r--libs/midi++2/midi++/events.h (renamed from libs/ardour/ardour/midi_events.h)0
-rw-r--r--libs/midi++2/midi++/jack.h14
24 files changed, 212 insertions, 104 deletions
diff --git a/libs/ardour/ardour/midi_buffer.h b/libs/ardour/ardour/midi_buffer.h
index b35264217a..a6cbb49118 100644
--- a/libs/ardour/ardour/midi_buffer.h
+++ b/libs/ardour/ardour/midi_buffer.h
@@ -20,8 +20,8 @@
#ifndef __ardour_midi_buffer_h__
#define __ardour_midi_buffer_h__
+#include <midi++/event.h>
#include <ardour/buffer.h>
-#include <ardour/midi_event.h>
namespace ARDOUR {
@@ -39,7 +39,7 @@ public:
void copy(const MidiBuffer& copy);
- bool push_back(const ARDOUR::MidiEvent& event);
+ bool push_back(const MIDI::Event& event);
bool push_back(const jack_midi_event_t& event);
Byte* reserve(double time, size_t size);
@@ -50,7 +50,7 @@ public:
struct iterator {
iterator(MidiBuffer& b, size_t i) : buffer(b), index(i) {}
- inline MidiEvent& operator*() const { return buffer[index]; }
+ inline MIDI::Event& operator*() const { return buffer[index]; }
inline iterator& operator++() { ++index; return *this; } // prefix
inline bool operator!=(const iterator& other) const { return index != other.index; }
@@ -61,7 +61,7 @@ public:
struct const_iterator {
const_iterator(const MidiBuffer& b, size_t i) : buffer(b), index(i) {}
- inline const MidiEvent& operator*() const { return buffer[index]; }
+ inline const MIDI::Event& operator*() const { return buffer[index]; }
inline const_iterator& operator++() { ++index; return *this; } // prefix
inline bool operator!=(const const_iterator& other) const { return index != other.index; }
@@ -80,8 +80,8 @@ private:
friend class iterator;
friend class const_iterator;
- const MidiEvent& operator[](size_t i) const { assert(i < _size); return _events[i]; }
- MidiEvent& operator[](size_t i) { assert(i < _size); return _events[i]; }
+ const MIDI::Event& operator[](size_t i) const { assert(i < _size); return _events[i]; }
+ MIDI::Event& operator[](size_t i) { assert(i < _size); return _events[i]; }
// FIXME: Eliminate this
static const size_t MAX_EVENT_SIZE = 4; // bytes
@@ -92,7 +92,7 @@ private:
/* FIXME: this is utter crap. rewrite as a flat/packed buffer like MidiRingBuffer */
- MidiEvent* _events; ///< Event structs that point to offsets in _data
+ MIDI::Event* _events; ///< Event structs that point to offsets in _data
Byte* _data; ///< MIDI, straight up. No time stamps.
};
diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h
index de31d0505e..11ef4e0f76 100644
--- a/libs/ardour/ardour/midi_model.h
+++ b/libs/ardour/ardour/midi_model.h
@@ -75,7 +75,7 @@ public:
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 MidiEvent& ev);
+ void append(const MIDI::Event& ev);
inline const boost::shared_ptr<const Note> note_at(unsigned i) const { return _notes[i]; }
inline const boost::shared_ptr<Note> note_at(unsigned i) { return _notes[i]; }
@@ -151,8 +151,8 @@ public:
inline bool locked() const { return _locked; }
- const MidiEvent& operator*() const { return _event; }
- const MidiEvent* operator->() const { return &_event; }
+ const MIDI::Event& operator*() const { return _event; }
+ const MIDI::Event* operator->() const { return &_event; }
const const_iterator& operator++(); // prefix only
bool operator==(const const_iterator& other) const;
@@ -164,7 +164,7 @@ public:
friend class MidiModel;
const MidiModel* _model;
- MidiEvent _event;
+ MIDI::Event _event;
typedef std::priority_queue<
boost::shared_ptr<Note>, std::deque< boost::shared_ptr<Note> >,
@@ -189,7 +189,7 @@ private:
void remove_note_unlocked(const boost::shared_ptr<const Note> note);
friend class const_iterator;
- bool control_to_midi_event(MidiEvent& ev, const MidiControlIterator& iter) const;
+ bool control_to_midi_event(MIDI::Event& ev, const MidiControlIterator& iter) const;
#ifndef NDEBUG
bool is_sorted() const;
diff --git a/libs/ardour/ardour/midi_ring_buffer.h b/libs/ardour/ardour/midi_ring_buffer.h
index a0078061ee..1b3ab50f91 100644
--- a/libs/ardour/ardour/midi_ring_buffer.h
+++ b/libs/ardour/ardour/midi_ring_buffer.h
@@ -307,7 +307,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
if (read_space() == 0)
return 0;
- MidiEvent ev;
+ MIDI::Event ev;
size_t count = 0;
diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h
index 5e41e3ff5b..d465506819 100644
--- a/libs/ardour/ardour/midi_source.h
+++ b/libs/ardour/ardour/midi_source.h
@@ -58,7 +58,7 @@ class MidiSource : public Source
virtual nframes_t midi_read (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset) const;
virtual nframes_t midi_write (MidiRingBuffer& src, nframes_t cnt);
- virtual void append_event_unlocked(EventTimeUnit unit, const MidiEvent& ev) = 0;
+ virtual void append_event_unlocked(EventTimeUnit unit, const MIDI::Event& ev) = 0;
virtual void mark_for_remove() = 0;
virtual void mark_streaming_midi_write_started (NoteMode mode, nframes_t start_time);
diff --git a/libs/ardour/ardour/midi_util.h b/libs/ardour/ardour/midi_util.h
index 1f121fbd68..efcb6a7cd5 100644
--- a/libs/ardour/ardour/midi_util.h
+++ b/libs/ardour/ardour/midi_util.h
@@ -21,7 +21,7 @@
#ifndef __ardour_midi_util_h__
#define __ardour_midi_util_h__
-#include <ardour/midi_events.h>
+#include <midi++/events.h>
namespace ARDOUR {
diff --git a/libs/ardour/ardour/note.h b/libs/ardour/ardour/note.h
index ea598573e8..41c18358d3 100644
--- a/libs/ardour/ardour/note.h
+++ b/libs/ardour/ardour/note.h
@@ -22,14 +22,14 @@
#define __ardour_note_h__
#include <stdint.h>
-#include <ardour/midi_event.h>
+#include <midi++/event.h>
namespace ARDOUR {
/** A MIDI Note.
*
- * A note is (unfortunately) special and not just another MidiEvent as it
+ * A note is (unfortunately) special and not just another MIDI::Event as it
* has a duration and two separate MIDI events (on and off).
*/
class Note {
@@ -53,16 +53,16 @@ public:
inline void set_velocity(uint8_t n) { _on_event.buffer()[2] = n; }
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 MIDI::Event& on_event() { return _on_event; }
+ inline MIDI::Event& off_event() { return _off_event; }
- inline const MidiEvent& on_event() const { return _on_event; }
- inline const MidiEvent& off_event() const { return _off_event; }
+ inline const MIDI::Event& on_event() const { return _on_event; }
+ inline const MIDI::Event& off_event() const { return _off_event; }
private:
// Event buffers are self-contained
- MidiEvent _on_event;
- MidiEvent _off_event;
+ MIDI::Event _on_event;
+ MIDI::Event _off_event;
};
diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h
index 937e08e44c..626aa64def 100644
--- a/libs/ardour/ardour/smf_source.h
+++ b/libs/ardour/ardour/smf_source.h
@@ -71,7 +71,7 @@ class SMFSource : public MidiSource {
void set_allow_remove_if_empty (bool yn);
void mark_for_remove();
- void append_event_unlocked(EventTimeUnit unit, const MidiEvent& ev);
+ void append_event_unlocked(EventTimeUnit unit, const MIDI::Event& ev);
int flush_header ();
int flush_footer ();
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index bdc1e8f0e4..84fd06d079 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -29,6 +29,8 @@
#include <pbd/stacktrace.h>
#include <pbd/unknown_type.h>
+#include <midi++/jack.h>
+
#include <ardour/audioengine.h>
#include <ardour/buffer.h>
#include <ardour/port.h>
@@ -113,6 +115,7 @@ _thread_init_callback (void *arg)
*/
PBD::ThreadCreatedWithRequestSize (pthread_self(), X_("Audioengine"), 4096);
+ MIDI::JACK_MidiPort::set_process_thread (pthread_self());
}
int
diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc
index 9a71303927..02c4a5ced6 100644
--- a/libs/ardour/globals.cc
+++ b/libs/ardour/globals.cc
@@ -412,21 +412,6 @@ ARDOUR::get_ardour_revision ()
return "$Rev$";
}
-static bool sae_binding_filter (const string& str, void* arg)
-{
- /* Not a dotfile, has a prefix before a period, suffix is ".bindings" and contains -sae- */
-
- return str[0] != '.' && str.length() > 13 && str.find (".bindings") == (str.length() - 9)
- && str.find ("SAE-") != string::npos;
-}
-
-static bool binding_filter (const string& str, void* arg)
-{
- /* Not a dotfile, has a prefix before a period, suffix is ".bindings" */
-
- return str[0] != '.' && str.length() > 9 && str.find (".bindings") == (str.length() - 9);
-}
-
void
ARDOUR::find_bindings_files (map<string,string>& files)
{
diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc
index a29cc1817b..104bef35c3 100644
--- a/libs/ardour/import.cc
+++ b/libs/ardour/import.cc
@@ -308,7 +308,7 @@ static void
write_midi_data_to_new_files (SMFReader* source, Session::import_status& status,
vector<boost::shared_ptr<Source> >& newfiles)
{
- MidiEvent ev(0.0, 4, NULL, true);
+ MIDI::Event ev(0.0, 4, NULL, true);
status.progress = 0.0f;
diff --git a/libs/ardour/jack_midi_port.cc b/libs/ardour/jack_midi_port.cc
index 0b8d96f4db..6d8e4c8c5d 100644
--- a/libs/ardour/jack_midi_port.cc
+++ b/libs/ardour/jack_midi_port.cc
@@ -82,7 +82,7 @@ JackMidiPort::cycle_end (nframes_t nframes, nframes_t offset)
jack_midi_clear_buffer (jack_buffer);
for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) {
- const MidiEvent& ev = *i;
+ const MIDI::Event& ev = *i;
// event times should be frames, relative to cycle start
assert(ev.time() >= 0);
assert(ev.time() < nframes);
diff --git a/libs/ardour/meter.cc b/libs/ardour/meter.cc
index f85fd3ec33..e75c1d89ca 100644
--- a/libs/ardour/meter.cc
+++ b/libs/ardour/meter.cc
@@ -47,7 +47,7 @@ PeakMeter::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_f
// GUI needs a better MIDI meter, not much information can be
// expressed through peaks alone
for (MidiBuffer::iterator i = bufs.get_midi(n).begin(); i != bufs.get_midi(n).end(); ++i) {
- const MidiEvent& ev = *i;
+ const MIDI::Event& ev = *i;
if (ev.is_note_on()) {
const float this_vel = log(ev.buffer()[2] / 127.0 * (M_E*M_E-M_E) + M_E) - 1.0;
//printf("V %d -> %f\n", (int)((Byte)ev.buffer[2]), this_vel);
diff --git a/libs/ardour/midi_buffer.cc b/libs/ardour/midi_buffer.cc
index 1ca6a5db72..a77a608fcd 100644
--- a/libs/ardour/midi_buffer.cc
+++ b/libs/ardour/midi_buffer.cc
@@ -74,10 +74,10 @@ MidiBuffer::resize (size_t size)
_capacity = size;
#ifdef NO_POSIX_MEMALIGN
- _events = (MidiEvent *) malloc(sizeof(MidiEvent) * _capacity);
+ _events = (MIDI::Event *) malloc(sizeof(MIDI::Event) * _capacity);
_data = (Byte *) malloc(sizeof(Byte) * _capacity * MAX_EVENT_SIZE);
#else
- posix_memalign((void**)&_events, CPU_CACHE_ALIGN, sizeof(MidiEvent) * _capacity);
+ posix_memalign((void**)&_events, CPU_CACHE_ALIGN, sizeof(MIDI::Event) * _capacity);
posix_memalign((void**)&_data, CPU_CACHE_ALIGN, sizeof(Byte) * _capacity * MAX_EVENT_SIZE);
#endif
assert(_data);
@@ -115,7 +115,7 @@ MidiBuffer::read_from(const Buffer& src, nframes_t nframes, nframes_t offset)
// FIXME: slow
for (size_t i=0; i < msrc.size(); ++i) {
- const MidiEvent& ev = msrc[i];
+ const MIDI::Event& ev = msrc[i];
if (ev.time() >= offset && ev.time() < offset+nframes) {
//cout << "MidiBuffer::read_from got event, " << ev.time() << endl;
push_back(ev);
@@ -136,7 +136,7 @@ MidiBuffer::read_from(const Buffer& src, nframes_t nframes, nframes_t offset)
* @return false if operation failed (not enough room)
*/
bool
-MidiBuffer::push_back(const MidiEvent& ev)
+MidiBuffer::push_back(const MIDI::Event& ev)
{
if (_size == _capacity)
return false;
@@ -222,7 +222,7 @@ MidiBuffer::silence(nframes_t dur, nframes_t offset)
if (offset != 0)
cerr << "WARNING: MidiBuffer::silence w/ offset != 0 (not implemented)" << endl;
- memset(_events, 0, sizeof(MidiEvent) * _capacity);
+ memset(_events, 0, sizeof(MIDI::Event) * _capacity);
memset(_data, 0, sizeof(Byte) * _capacity * MAX_EVENT_SIZE);
_size = 0;
_silent = true;
@@ -261,8 +261,8 @@ MidiBuffer::merge(const MidiBuffer& a, const MidiBuffer& b)
push_back(b[b_index]);
++b_index;
} else {
- const MidiEvent& a_ev = a[a_index];
- const MidiEvent& b_ev = b[b_index];
+ const MIDI::Event& a_ev = a[a_index];
+ const MIDI::Event& b_ev = b[b_index];
if (a_ev.time() <= b_ev.time()) {
push_back(a_ev);
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index 7c3bc73fb8..51f093919c 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -548,7 +548,7 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t
MidiBuffer::iterator port_iter = _source_port->get_midi_buffer().begin();
for (size_t i=0; i < to_write; ++i) {
- const MidiEvent& ev = *port_iter;
+ const MIDI::Event& ev = *port_iter;
_capture_buf->write(ev.time() + transport_frame, ev.size(), ev.buffer());
++port_iter;
}
diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc
index 6bd351a6dc..a49094df91 100644
--- a/libs/ardour/midi_model.cc
+++ b/libs/ardour/midi_model.cc
@@ -25,8 +25,9 @@
#include <stdexcept>
#include <stdint.h>
#include <pbd/enumwriter.h>
+#include <midi++/events.h>
+
#include <ardour/midi_model.h>
-#include <ardour/midi_events.h>
#include <ardour/midi_source.h>
#include <ardour/types.h>
#include <ardour/session.h>
@@ -92,7 +93,7 @@ MidiModel::const_iterator::const_iterator(const MidiModel& model, double t)
}
if (_note_iter != model.notes().end()) {
- _event = MidiEvent((*_note_iter)->on_event(), false);
+ _event = MIDI::Event((*_note_iter)->on_event(), false);
_active_notes.push(*_note_iter);
++_note_iter;
}
@@ -182,12 +183,12 @@ MidiModel::const_iterator::operator++()
if (type == NOTE_ON) {
//cerr << "********** MIDI Iterator = note on" << endl;
- _event = MidiEvent((*_note_iter)->on_event(), false);
+ _event = MIDI::Event((*_note_iter)->on_event(), false);
_active_notes.push(*_note_iter);
++_note_iter;
} else if (type == NOTE_OFF) {
//cerr << "********** MIDI Iterator = note off" << endl;
- _event = MidiEvent(_active_notes.top()->off_event(), false);
+ _event = MIDI::Event(_active_notes.top()->off_event(), false);
_active_notes.pop();
} else if (type == CC) {
//cerr << "********** MIDI Iterator = CC" << endl;
@@ -291,7 +292,7 @@ MidiModel::read(MidiRingBuffer& dst, nframes_t start, nframes_t nframes, nframes
bool
-MidiModel::control_to_midi_event(MidiEvent& ev, const MidiControlIterator& iter) const
+MidiModel::control_to_midi_event(MIDI::Event& ev, const MidiControlIterator& iter) const
{
if (iter.first->parameter().type() == MidiCCAutomation) {
if (ev.size() < 3)
@@ -378,7 +379,7 @@ MidiModel::end_write(bool delete_stuck)
* and MUST be >= the latest event currently in the model.
*/
void
-MidiModel::append(const MidiEvent& ev)
+MidiModel::append(const MIDI::Event& ev)
{
write_lock();
@@ -643,7 +644,7 @@ MidiModel::write_to(boost::shared_ptr<MidiSource> source)
/* Percussive
for (Notes::const_iterator n = _notes.begin(); n != _notes.end(); ++n) {
- const MidiEvent& ev = n->on_event();
+ const MIDI::Event& ev = n->on_event();
source->append_event_unlocked(ev);
}*/
@@ -658,7 +659,7 @@ MidiModel::write_to(boost::shared_ptr<MidiSource> source)
// Write any pending note offs earlier than this note on
while ( ! active_notes.empty() ) {
const boost::shared_ptr<const Note> earliest_off = active_notes.top();
- const MidiEvent& off_ev = earliest_off->off_event();
+ const MIDI::Event& off_ev = earliest_off->off_event();
if (off_ev.time() <= (*n)->time()) {
source->append_event_unlocked(Frames, off_ev);
active_notes.pop();
diff --git a/libs/ardour/midi_stretch.cc b/libs/ardour/midi_stretch.cc
index f214bde0be..f33c58a0fd 100644
--- a/libs/ardour/midi_stretch.cc
+++ b/libs/ardour/midi_stretch.cc
@@ -91,7 +91,7 @@ MidiStretch::run (boost::shared_ptr<Region> r)
const double new_time = i->time() * _request.time_fraction;
// FIXME: double copy
- MidiEvent ev = MidiEvent(*i, true);
+ MIDI::Event ev = MIDI::Event(*i, true);
ev.time() = new_time;
new_model->append(ev);
}
@@ -101,7 +101,7 @@ MidiStretch::run (boost::shared_ptr<Region> r)
const int ret = finish (region, nsrcs, new_name);
- results[0]->set_length(r->length() * _request.time_fraction, NULL);
+ results[0]->set_length((nframes_t) floor (r->length() * _request.time_fraction), NULL);
return ret;
}
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index e1fa109342..bf97b19106 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -22,6 +22,7 @@
#include <sigc++/bind.h>
#include <pbd/enumwriter.h>
+#include <midi++/events.h>
#include <ardour/midi_track.h>
#include <ardour/midi_diskstream.h>
@@ -36,7 +37,7 @@
#include <ardour/utils.h>
#include <ardour/buffer_set.h>
#include <ardour/meter.h>
-#include <ardour/midi_events.h>
+
#include "i18n.h"
@@ -587,7 +588,7 @@ MidiTrack::write_controller_messages(MidiBuffer& output_buf, nframes_t start_fra
Byte buf[3]; // CC = 3 bytes
buf[0] = MIDI_CMD_CONTROL;
- MidiEvent ev(0, 3, buf, false);
+ MIDI::Event ev(0, 3, buf, false);
// Write track controller automation
#if 0
diff --git a/libs/ardour/smf_reader.cc b/libs/ardour/smf_reader.cc
index 20204f1d32..63a020f141 100644
--- a/libs/ardour/smf_reader.cc
+++ b/libs/ardour/smf_reader.cc
@@ -21,8 +21,9 @@
#include <cassert>
#include <iostream>
#include <glibmm/miscutils.h>
+#include <midi++/events.h>
+
#include <ardour/smf_reader.h>
-#include <ardour/midi_events.h>
#include <ardour/midi_util.h>
using namespace std;
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index bd4f837780..720626e936 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -432,7 +432,7 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
assert(time >= _timeline_position);
time -= _timeline_position;
- const MidiEvent ev(time, size, buf);
+ const MIDI::Event ev(time, size, buf);
append_event_unlocked(Frames, ev);
if (_model)
@@ -452,7 +452,7 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
void
-SMFSource::append_event_unlocked(EventTimeUnit unit, const MidiEvent& ev)
+SMFSource::append_event_unlocked(EventTimeUnit unit, const MIDI::Event& ev)
{
/*printf("%s - append chan = %u, time = %lf, size = %u, data = ", _path.c_str(),
(unsigned)ev.channel(), ev.time(), ev.size());
@@ -886,7 +886,7 @@ SMFSource::load_model(bool lock, bool force_reload)
fseek(_fd, _header_size, 0);
uint64_t time = 0; /* in SMF ticks */
- MidiEvent ev;
+ MIDI::Event ev;
size_t scratch_size = 0; // keep track of scratch and minimize reallocs
diff --git a/libs/midi++2/SConscript b/libs/midi++2/SConscript
index 14c0282396..3e2e204fbd 100644
--- a/libs/midi++2/SConscript
+++ b/libs/midi++2/SConscript
@@ -7,7 +7,13 @@ import glob
Import('env libraries install_prefix')
midi2 = env.Copy()
-midi2.Merge([ libraries['sigc2'], libraries['xml'], libraries['glibmm2'], libraries['glib2'], libraries['pbd'], libraries['jack'] ])
+midi2.Merge([ libraries['sigc2'],
+ libraries['xml'],
+ libraries['glibmm2'],
+ libraries['glib2'],
+ libraries['pbd'],
+ libraries['jack']
+ ])
if midi2['IS_OSX']:
midi2.Append (LINKFLAGS="-Xlinker -headerpad -Xlinker 2048")
diff --git a/libs/midi++2/jack_midiport.cc b/libs/midi++2/jack_midiport.cc
index 52d05a5cfb..9b2f07d326 100644
--- a/libs/midi++2/jack_midiport.cc
+++ b/libs/midi++2/jack_midiport.cc
@@ -30,12 +30,15 @@ using namespace std;
using namespace MIDI;
using namespace PBD;
+pthread_t JACK_MidiPort::_process_thread;
+
JACK_MidiPort::JACK_MidiPort(const XMLNode& node, jack_client_t* jack_client)
: Port(node)
, _jack_client(jack_client)
, _jack_input_port(NULL)
, _jack_output_port(NULL)
, _last_read_index(0)
+ , non_process_thread_fifo (5 * 1024)
{
int err = create_ports (node);
@@ -55,23 +58,85 @@ JACK_MidiPort::cycle_start (nframes_t nframes)
Port::cycle_start(nframes);
assert(_nframes_this_cycle == nframes);
_last_read_index = 0;
- jack_midi_clear_buffer(jack_port_get_buffer(_jack_output_port, nframes));
+
+ void *buffer = jack_port_get_buffer (_jack_output_port, nframes);
+ jack_midi_clear_buffer (buffer);
+ flush (buffer);
}
int
JACK_MidiPort::write(byte * msg, size_t msglen, timestamp_t timestamp)
{
- if (!_currently_in_cycle) {
- error << "JACK MIDI write ignored - not in cycle ... FIX ME PAUL!" << endmsg;
+ if (!is_process_thread()) {
+
+ Glib::Mutex::Lock lm (non_process_thread_fifo_lock);
+ RingBuffer<Event>::rw_vector vec;
+
+ non_process_thread_fifo.get_write_vector (&vec);
+
+ cerr << "Non-process thread writes " << msglen << " to " << name() << endl;
+
+ if (vec.len[0] + vec.len[1] < 1) {
+ error << "no space in FIFO for non-process thread MIDI write"
+ << endmsg;
+ return 0;
+ }
+
+ if (vec.len[0]) {
+ vec.buf[0]->set (msg, msglen, timestamp);
+ } else {
+ vec.buf[1]->set (msg, msglen, timestamp);
+ }
+
+ non_process_thread_fifo.increment_write_idx (1);
+
return msglen;
+
+ } else {
+
+ assert(_currently_in_cycle);
+ assert(timestamp < _nframes_this_cycle);
+ assert(_jack_output_port);
+
+ // FIXME: return value correct?
+ return jack_midi_event_write (jack_port_get_buffer (_jack_output_port, _nframes_this_cycle),
+ timestamp, msg, msglen);
}
- assert(timestamp < _nframes_this_cycle);
- assert(_jack_output_port);
+}
+
+void
+JACK_MidiPort::flush (void* jack_port_buffer)
+{
+ RingBuffer<Event>::rw_vector vec;
+ size_t written;
- // FIXME: return value correct?
- return jack_midi_event_write (
- jack_port_get_buffer(_jack_output_port, _nframes_this_cycle),
- timestamp, msg, msglen);
+ non_process_thread_fifo.get_read_vector (&vec);
+
+ if (vec.len[0] + vec.len[1]) {
+ cerr << "Flush " << vec.len[0] + vec.len[1] << "events from non-process FIFO\n";
+ }
+
+ if (vec.len[0]) {
+ Event* evp = vec.buf[0];
+
+ for (size_t n = 0; n < vec.len[0]; ++n, ++evp) {
+ jack_midi_event_write (jack_port_buffer,
+ (timestamp_t) evp->time(), evp->buffer(), evp->size());
+ }
+ }
+
+ if (vec.len[1]) {
+ Event* evp = vec.buf[1];
+
+ for (size_t n = 0; n < vec.len[1]; ++n, ++evp) {
+ jack_midi_event_write (jack_port_buffer,
+ (timestamp_t) evp->time(), evp->buffer(), evp->size());
+ }
+ }
+
+ if ((written = vec.len[0] + vec.len[1]) != 0) {
+ non_process_thread_fifo.increment_read_idx (written);
+ }
}
int
@@ -137,3 +202,15 @@ void
JACK_MidiPort::set_state (const XMLNode& node)
{
}
+
+void
+JACK_MidiPort::set_process_thread (pthread_t thr)
+{
+ _process_thread = thr;
+}
+
+bool
+JACK_MidiPort::is_process_thread()
+{
+ return (pthread_self() == _process_thread);
+}
diff --git a/libs/ardour/ardour/midi_event.h b/libs/midi++2/midi++/event.h
index 7dafb0fbcf..6ef1c49ee9 100644
--- a/libs/ardour/ardour/midi_event.h
+++ b/libs/midi++2/midi++/event.h
@@ -18,19 +18,24 @@
*/
-#ifndef __ardour_midi_event_h__
-#define __ardour_midi_event_h__
+#ifndef __libmidipp_midi_event_h__
+#define __libmidipp_midi_event_h__
-#include <ardour/types.h>
-#include <ardour/midi_events.h>
#include <stdint.h>
+#include <cstdlib>
+#include <cstring>
+#include <assert.h>
+
+#include <midi++/types.h>
+#include <midi++/events.h>
/** If this is not defined, all methods of MidiEvent are RT safe
* but MidiEvent will never deep copy and (depending on the scenario)
- * may not be usable in STL containers, signals, etc. */
+ * may not be usable in STL containers, signals, etc.
+ */
#define MIDI_EVENT_ALLOW_ALLOC 1
-namespace ARDOUR {
+namespace MIDI {
/** Identical to jack_midi_event_t, but with double timestamp
@@ -38,16 +43,16 @@ namespace ARDOUR {
* time is either a frame time (from/to Jack) or a beat time (internal
* tempo time, used in MidiModel) depending on context.
*/
-struct MidiEvent {
+struct Event {
#ifdef MIDI_EVENT_ALLOW_ALLOC
- MidiEvent(double t=0, uint32_t s=0, Byte* b=NULL, bool owns_buffer=false)
+ Event(double t=0, uint32_t s=0, uint8_t* b=NULL, bool owns_buffer=false)
: _time(t)
, _size(s)
, _buffer(b)
, _owns_buffer(owns_buffer)
{
if (owns_buffer) {
- _buffer = (Byte*)malloc(_size);
+ _buffer = (uint8_t*)malloc(_size);
if (b)
memcpy(_buffer, b, _size);
else
@@ -61,14 +66,14 @@ struct MidiEvent {
* is NOT REALTIME SAFE. Otherwise both events share a buffer and
* memory management semantics are the caller's problem.
*/
- MidiEvent(const MidiEvent& copy, bool owns_buffer)
+ Event(const Event& copy, bool owns_buffer)
: _time(copy._time)
, _size(copy._size)
, _buffer(copy._buffer)
, _owns_buffer(owns_buffer)
{
if (owns_buffer) {
- _buffer = (Byte*)malloc(_size);
+ _buffer = (uint8_t*)malloc(_size);
if (copy._buffer)
memcpy(_buffer, copy._buffer, _size);
else
@@ -76,17 +81,17 @@ struct MidiEvent {
}
}
- ~MidiEvent() {
+ ~Event() {
if (_owns_buffer)
free(_buffer);
}
- inline const MidiEvent& operator=(const MidiEvent& copy) {
+ inline const Event& operator=(const Event& copy) {
_time = copy._time;
if (_owns_buffer) {
if (copy._buffer) {
if (!_buffer || _size < copy._size)
- _buffer = (Byte*)::realloc(_buffer, copy._size);
+ _buffer = (uint8_t*)::realloc(_buffer, copy._size);
memcpy(_buffer, copy._buffer, copy._size);
} else {
free(_buffer);
@@ -100,7 +105,22 @@ struct MidiEvent {
return *this;
}
- inline bool operator==(const MidiEvent& other) const {
+ inline void set (uint8_t* msg, size_t msglen, timestamp_t t) {
+ if (_owns_buffer) {
+ if (_size < msglen) {
+ free (_buffer);
+ _buffer = (uint8_t*) malloc (msglen);
+ }
+ } else {
+ _buffer = (uint8_t*) malloc (msglen);
+ _owns_buffer = true;
+ }
+
+ memcpy (_buffer, msg, msglen);
+ _time = t;
+ }
+
+ inline bool operator==(const Event& other) const {
if (_time != other._time)
return false;
@@ -117,11 +137,11 @@ struct MidiEvent {
return true;
}
- inline bool operator!=(const MidiEvent& other) const { return ! operator==(other); }
+ inline bool operator!=(const Event& other) const { return ! operator==(other); }
inline bool owns_buffer() const { return _owns_buffer; }
- inline void set_buffer(Byte* buf, bool own) {
+ inline void set_buffer(uint8_t* buf, bool own) {
if (_owns_buffer) {
free(_buffer);
_buffer = NULL;
@@ -132,12 +152,12 @@ struct MidiEvent {
inline void realloc(size_t size) {
assert(_owns_buffer);
- _buffer = (Byte*) ::realloc(_buffer, size);
+ _buffer = (uint8_t*) ::realloc(_buffer, size);
}
#else
- inline void set_buffer(Byte* buf) { _buffer = buf; }
+ inline void set_buffer(uint8_t* buf) { _buffer = buf; }
#endif // MIDI_EVENT_ALLOW_ALLOC
@@ -147,21 +167,21 @@ struct MidiEvent {
inline uint32_t& size() { return _size; }
inline uint8_t type() const { return (_buffer[0] & 0xF0); }
inline uint8_t channel() const { return (_buffer[0] & 0x0F); }
- inline bool is_note_on() const { return (type() == MIDI_CMD_NOTE_ON); }
- inline bool is_note_off() const { return (type() == MIDI_CMD_NOTE_OFF); }
- inline bool is_cc() const { return (type() == MIDI_CMD_CONTROL); }
+ inline bool is_note_on() const { return (type() == MIDI_CMD_NOTE_ON); }
+ inline bool is_note_off() const { return (type() == MIDI_CMD_NOTE_OFF); }
+ inline bool is_cc() const { return (type() == MIDI_CMD_CONTROL); }
inline bool is_note() const { return (is_note_on() || is_note_off()); }
inline uint8_t note() const { return (_buffer[1]); }
inline uint8_t velocity() const { return (_buffer[2]); }
inline uint8_t cc_number() const { return (_buffer[1]); }
inline uint8_t cc_value() const { return (_buffer[2]); }
- inline const Byte* buffer() const { return _buffer; }
- inline Byte*& buffer() { return _buffer; }
+ inline const uint8_t* buffer() const { return _buffer; }
+ inline uint8_t*& buffer() { return _buffer; }
private:
double _time; /**< Sample index (or beat time) at which event is valid */
- uint32_t _size; /**< Number of bytes of data in \a buffer */
- Byte* _buffer; /**< Raw MIDI data */
+ uint32_t _size; /**< Number of uint8_ts of data in \a buffer */
+ uint8_t* _buffer; /**< Raw MIDI data */
#ifdef MIDI_EVENT_ALLOW_ALLOC
bool _owns_buffer; /**< Whether buffer is locally allocated */
@@ -169,6 +189,6 @@ private:
};
-} // namespace ARDOUR
+}
-#endif /* __ardour_midi_event_h__ */
+#endif /* __libmidipp_midi_event_h__ */
diff --git a/libs/ardour/ardour/midi_events.h b/libs/midi++2/midi++/events.h
index f7e2442109..f7e2442109 100644
--- a/libs/ardour/ardour/midi_events.h
+++ b/libs/midi++2/midi++/events.h
diff --git a/libs/midi++2/midi++/jack.h b/libs/midi++2/midi++/jack.h
index 845dd0c229..291b87f835 100644
--- a/libs/midi++2/midi++/jack.h
+++ b/libs/midi++2/midi++/jack.h
@@ -28,9 +28,13 @@
#include <fcntl.h>
#include <unistd.h>
+#include <glibmm/thread.h>
+
+#include <pbd/ringbuffer.h>
#include <jack/jack.h>
#include <jack/midiport.h>
#include <midi++/port.h>
+#include <midi++/event.h>
namespace MIDI
{
@@ -52,6 +56,8 @@ public:
virtual XMLNode& get_state () const;
virtual void set_state (const XMLNode&);
+ static void set_process_thread (pthread_t);
+
protected:
std::string get_typestring () const {
return typestring;
@@ -69,6 +75,14 @@ private:
jack_port_t* _jack_input_port;
jack_port_t* _jack_output_port;
nframes_t _last_read_index;
+
+ void flush (void* jack_port_buffer);
+
+ static pthread_t _process_thread;
+ static bool is_process_thread();
+
+ RingBuffer<MIDI::Event> non_process_thread_fifo;
+ Glib::Mutex non_process_thread_fifo_lock;
};