mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-10 16:46:35 +01:00
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
This commit is contained in:
parent
d69f4e9e3d
commit
eb4a1fdbb8
27 changed files with 214 additions and 109 deletions
|
|
@ -29,7 +29,6 @@
|
||||||
#include <ardour/midi_source.h>
|
#include <ardour/midi_source.h>
|
||||||
#include <ardour/midi_diskstream.h>
|
#include <ardour/midi_diskstream.h>
|
||||||
#include <ardour/midi_track.h>
|
#include <ardour/midi_track.h>
|
||||||
#include <ardour/midi_events.h>
|
|
||||||
#include <ardour/smf_source.h>
|
#include <ardour/smf_source.h>
|
||||||
#include <ardour/region_factory.h>
|
#include <ardour/region_factory.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@
|
||||||
#include <ardour/midi_region.h>
|
#include <ardour/midi_region.h>
|
||||||
#include <ardour/midi_source.h>
|
#include <ardour/midi_source.h>
|
||||||
#include <ardour/midi_diskstream.h>
|
#include <ardour/midi_diskstream.h>
|
||||||
#include <ardour/midi_events.h>
|
|
||||||
#include <ardour/midi_model.h>
|
#include <ardour/midi_model.h>
|
||||||
|
|
||||||
#include "streamview.h"
|
#include "streamview.h"
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@
|
||||||
#include <ardour/midi_source.h>
|
#include <ardour/midi_source.h>
|
||||||
#include <ardour/midi_diskstream.h>
|
#include <ardour/midi_diskstream.h>
|
||||||
#include <ardour/midi_track.h>
|
#include <ardour/midi_track.h>
|
||||||
#include <ardour/midi_events.h>
|
|
||||||
#include <ardour/smf_source.h>
|
#include <ardour/smf_source.h>
|
||||||
#include <ardour/region_factory.h>
|
#include <ardour/region_factory.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@
|
||||||
#ifndef __ardour_midi_buffer_h__
|
#ifndef __ardour_midi_buffer_h__
|
||||||
#define __ardour_midi_buffer_h__
|
#define __ardour_midi_buffer_h__
|
||||||
|
|
||||||
|
#include <midi++/event.h>
|
||||||
#include <ardour/buffer.h>
|
#include <ardour/buffer.h>
|
||||||
#include <ardour/midi_event.h>
|
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
|
@ -39,7 +39,7 @@ public:
|
||||||
|
|
||||||
void copy(const MidiBuffer& copy);
|
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);
|
bool push_back(const jack_midi_event_t& event);
|
||||||
Byte* reserve(double time, size_t size);
|
Byte* reserve(double time, size_t size);
|
||||||
|
|
||||||
|
|
@ -50,7 +50,7 @@ public:
|
||||||
struct iterator {
|
struct iterator {
|
||||||
iterator(MidiBuffer& b, size_t i) : buffer(b), index(i) {}
|
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 iterator& operator++() { ++index; return *this; } // prefix
|
||||||
inline bool operator!=(const iterator& other) const { return index != other.index; }
|
inline bool operator!=(const iterator& other) const { return index != other.index; }
|
||||||
|
|
||||||
|
|
@ -61,7 +61,7 @@ public:
|
||||||
struct const_iterator {
|
struct const_iterator {
|
||||||
const_iterator(const MidiBuffer& b, size_t i) : buffer(b), index(i) {}
|
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 const_iterator& operator++() { ++index; return *this; } // prefix
|
||||||
inline bool operator!=(const const_iterator& other) const { return index != other.index; }
|
inline bool operator!=(const const_iterator& other) const { return index != other.index; }
|
||||||
|
|
||||||
|
|
@ -80,8 +80,8 @@ private:
|
||||||
friend class iterator;
|
friend class iterator;
|
||||||
friend class const_iterator;
|
friend class const_iterator;
|
||||||
|
|
||||||
const MidiEvent& operator[](size_t i) const { assert(i < _size); return _events[i]; }
|
const MIDI::Event& operator[](size_t i) const { assert(i < _size); return _events[i]; }
|
||||||
MidiEvent& operator[](size_t i) { assert(i < _size); return _events[i]; }
|
MIDI::Event& operator[](size_t i) { assert(i < _size); return _events[i]; }
|
||||||
|
|
||||||
// FIXME: Eliminate this
|
// FIXME: Eliminate this
|
||||||
static const size_t MAX_EVENT_SIZE = 4; // bytes
|
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 */
|
/* 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.
|
Byte* _data; ///< MIDI, straight up. No time stamps.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ public:
|
||||||
size_t read (MidiRingBuffer& dst, nframes_t start, nframes_t nframes, nframes_t stamp_offset) const;
|
size_t read (MidiRingBuffer& dst, nframes_t start, nframes_t nframes, nframes_t stamp_offset) const;
|
||||||
|
|
||||||
/** Resizes vector if necessary (NOT realtime safe) */
|
/** 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<const Note> note_at(unsigned i) const { return _notes[i]; }
|
||||||
inline const boost::shared_ptr<Note> note_at(unsigned i) { 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; }
|
inline bool locked() const { return _locked; }
|
||||||
|
|
||||||
const MidiEvent& operator*() const { return _event; }
|
const MIDI::Event& operator*() const { return _event; }
|
||||||
const MidiEvent* operator->() const { return &_event; }
|
const MIDI::Event* operator->() const { return &_event; }
|
||||||
|
|
||||||
const const_iterator& operator++(); // prefix only
|
const const_iterator& operator++(); // prefix only
|
||||||
bool operator==(const const_iterator& other) const;
|
bool operator==(const const_iterator& other) const;
|
||||||
|
|
@ -164,7 +164,7 @@ public:
|
||||||
friend class MidiModel;
|
friend class MidiModel;
|
||||||
|
|
||||||
const MidiModel* _model;
|
const MidiModel* _model;
|
||||||
MidiEvent _event;
|
MIDI::Event _event;
|
||||||
|
|
||||||
typedef std::priority_queue<
|
typedef std::priority_queue<
|
||||||
boost::shared_ptr<Note>, std::deque< boost::shared_ptr<Note> >,
|
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);
|
void remove_note_unlocked(const boost::shared_ptr<const Note> note);
|
||||||
|
|
||||||
friend class const_iterator;
|
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
|
#ifndef NDEBUG
|
||||||
bool is_sorted() const;
|
bool is_sorted() const;
|
||||||
|
|
|
||||||
|
|
@ -307,7 +307,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
|
||||||
if (read_space() == 0)
|
if (read_space() == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
MidiEvent ev;
|
MIDI::Event ev;
|
||||||
|
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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_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 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_for_remove() = 0;
|
||||||
virtual void mark_streaming_midi_write_started (NoteMode mode, nframes_t start_time);
|
virtual void mark_streaming_midi_write_started (NoteMode mode, nframes_t start_time);
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
#ifndef __ardour_midi_util_h__
|
#ifndef __ardour_midi_util_h__
|
||||||
#define __ardour_midi_util_h__
|
#define __ardour_midi_util_h__
|
||||||
|
|
||||||
#include <ardour/midi_events.h>
|
#include <midi++/events.h>
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,14 @@
|
||||||
#define __ardour_note_h__
|
#define __ardour_note_h__
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <ardour/midi_event.h>
|
#include <midi++/event.h>
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
|
||||||
/** A MIDI Note.
|
/** 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).
|
* has a duration and two separate MIDI events (on and off).
|
||||||
*/
|
*/
|
||||||
class Note {
|
class Note {
|
||||||
|
|
@ -53,16 +53,16 @@ public:
|
||||||
inline void set_velocity(uint8_t n) { _on_event.buffer()[2] = n; }
|
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 void set_duration(double d) { _off_event.time() = _on_event.time() + d; }
|
||||||
|
|
||||||
inline MidiEvent& on_event() { return _on_event; }
|
inline MIDI::Event& on_event() { return _on_event; }
|
||||||
inline MidiEvent& off_event() { return _off_event; }
|
inline MIDI::Event& off_event() { return _off_event; }
|
||||||
|
|
||||||
inline const MidiEvent& on_event() const { return _on_event; }
|
inline const MIDI::Event& on_event() const { return _on_event; }
|
||||||
inline const MidiEvent& off_event() const { return _off_event; }
|
inline const MIDI::Event& off_event() const { return _off_event; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Event buffers are self-contained
|
// Event buffers are self-contained
|
||||||
MidiEvent _on_event;
|
MIDI::Event _on_event;
|
||||||
MidiEvent _off_event;
|
MIDI::Event _off_event;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ class SMFSource : public MidiSource {
|
||||||
void set_allow_remove_if_empty (bool yn);
|
void set_allow_remove_if_empty (bool yn);
|
||||||
void mark_for_remove();
|
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_header ();
|
||||||
int flush_footer ();
|
int flush_footer ();
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@
|
||||||
#include <pbd/stacktrace.h>
|
#include <pbd/stacktrace.h>
|
||||||
#include <pbd/unknown_type.h>
|
#include <pbd/unknown_type.h>
|
||||||
|
|
||||||
|
#include <midi++/jack.h>
|
||||||
|
|
||||||
#include <ardour/audioengine.h>
|
#include <ardour/audioengine.h>
|
||||||
#include <ardour/buffer.h>
|
#include <ardour/buffer.h>
|
||||||
#include <ardour/port.h>
|
#include <ardour/port.h>
|
||||||
|
|
@ -113,6 +115,7 @@ _thread_init_callback (void *arg)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PBD::ThreadCreatedWithRequestSize (pthread_self(), X_("Audioengine"), 4096);
|
PBD::ThreadCreatedWithRequestSize (pthread_self(), X_("Audioengine"), 4096);
|
||||||
|
MIDI::JACK_MidiPort::set_process_thread (pthread_self());
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
||||||
|
|
@ -412,21 +412,6 @@ ARDOUR::get_ardour_revision ()
|
||||||
return "$Rev$";
|
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
|
void
|
||||||
ARDOUR::find_bindings_files (map<string,string>& files)
|
ARDOUR::find_bindings_files (map<string,string>& files)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -308,7 +308,7 @@ static void
|
||||||
write_midi_data_to_new_files (SMFReader* source, Session::import_status& status,
|
write_midi_data_to_new_files (SMFReader* source, Session::import_status& status,
|
||||||
vector<boost::shared_ptr<Source> >& newfiles)
|
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;
|
status.progress = 0.0f;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ JackMidiPort::cycle_end (nframes_t nframes, nframes_t offset)
|
||||||
jack_midi_clear_buffer (jack_buffer);
|
jack_midi_clear_buffer (jack_buffer);
|
||||||
|
|
||||||
for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) {
|
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
|
// event times should be frames, relative to cycle start
|
||||||
assert(ev.time() >= 0);
|
assert(ev.time() >= 0);
|
||||||
assert(ev.time() < nframes);
|
assert(ev.time() < nframes);
|
||||||
|
|
|
||||||
|
|
@ -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
|
// GUI needs a better MIDI meter, not much information can be
|
||||||
// expressed through peaks alone
|
// expressed through peaks alone
|
||||||
for (MidiBuffer::iterator i = bufs.get_midi(n).begin(); i != bufs.get_midi(n).end(); ++i) {
|
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()) {
|
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;
|
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);
|
//printf("V %d -> %f\n", (int)((Byte)ev.buffer[2]), this_vel);
|
||||||
|
|
|
||||||
|
|
@ -74,10 +74,10 @@ MidiBuffer::resize (size_t size)
|
||||||
_capacity = size;
|
_capacity = size;
|
||||||
|
|
||||||
#ifdef NO_POSIX_MEMALIGN
|
#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);
|
_data = (Byte *) malloc(sizeof(Byte) * _capacity * MAX_EVENT_SIZE);
|
||||||
#else
|
#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);
|
posix_memalign((void**)&_data, CPU_CACHE_ALIGN, sizeof(Byte) * _capacity * MAX_EVENT_SIZE);
|
||||||
#endif
|
#endif
|
||||||
assert(_data);
|
assert(_data);
|
||||||
|
|
@ -115,7 +115,7 @@ MidiBuffer::read_from(const Buffer& src, nframes_t nframes, nframes_t offset)
|
||||||
|
|
||||||
// FIXME: slow
|
// FIXME: slow
|
||||||
for (size_t i=0; i < msrc.size(); ++i) {
|
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) {
|
if (ev.time() >= offset && ev.time() < offset+nframes) {
|
||||||
//cout << "MidiBuffer::read_from got event, " << ev.time() << endl;
|
//cout << "MidiBuffer::read_from got event, " << ev.time() << endl;
|
||||||
push_back(ev);
|
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)
|
* @return false if operation failed (not enough room)
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
MidiBuffer::push_back(const MidiEvent& ev)
|
MidiBuffer::push_back(const MIDI::Event& ev)
|
||||||
{
|
{
|
||||||
if (_size == _capacity)
|
if (_size == _capacity)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -222,7 +222,7 @@ MidiBuffer::silence(nframes_t dur, nframes_t offset)
|
||||||
if (offset != 0)
|
if (offset != 0)
|
||||||
cerr << "WARNING: MidiBuffer::silence w/ offset != 0 (not implemented)" << endl;
|
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);
|
memset(_data, 0, sizeof(Byte) * _capacity * MAX_EVENT_SIZE);
|
||||||
_size = 0;
|
_size = 0;
|
||||||
_silent = true;
|
_silent = true;
|
||||||
|
|
@ -261,8 +261,8 @@ MidiBuffer::merge(const MidiBuffer& a, const MidiBuffer& b)
|
||||||
push_back(b[b_index]);
|
push_back(b[b_index]);
|
||||||
++b_index;
|
++b_index;
|
||||||
} else {
|
} else {
|
||||||
const MidiEvent& a_ev = a[a_index];
|
const MIDI::Event& a_ev = a[a_index];
|
||||||
const MidiEvent& b_ev = b[b_index];
|
const MIDI::Event& b_ev = b[b_index];
|
||||||
|
|
||||||
if (a_ev.time() <= b_ev.time()) {
|
if (a_ev.time() <= b_ev.time()) {
|
||||||
push_back(a_ev);
|
push_back(a_ev);
|
||||||
|
|
|
||||||
|
|
@ -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();
|
MidiBuffer::iterator port_iter = _source_port->get_midi_buffer().begin();
|
||||||
|
|
||||||
for (size_t i=0; i < to_write; ++i) {
|
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());
|
_capture_buf->write(ev.time() + transport_frame, ev.size(), ev.buffer());
|
||||||
++port_iter;
|
++port_iter;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,9 @@
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <pbd/enumwriter.h>
|
#include <pbd/enumwriter.h>
|
||||||
|
#include <midi++/events.h>
|
||||||
|
|
||||||
#include <ardour/midi_model.h>
|
#include <ardour/midi_model.h>
|
||||||
#include <ardour/midi_events.h>
|
|
||||||
#include <ardour/midi_source.h>
|
#include <ardour/midi_source.h>
|
||||||
#include <ardour/types.h>
|
#include <ardour/types.h>
|
||||||
#include <ardour/session.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()) {
|
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);
|
_active_notes.push(*_note_iter);
|
||||||
++_note_iter;
|
++_note_iter;
|
||||||
}
|
}
|
||||||
|
|
@ -182,12 +183,12 @@ MidiModel::const_iterator::operator++()
|
||||||
|
|
||||||
if (type == NOTE_ON) {
|
if (type == NOTE_ON) {
|
||||||
//cerr << "********** MIDI Iterator = note on" << endl;
|
//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);
|
_active_notes.push(*_note_iter);
|
||||||
++_note_iter;
|
++_note_iter;
|
||||||
} else if (type == NOTE_OFF) {
|
} else if (type == NOTE_OFF) {
|
||||||
//cerr << "********** MIDI Iterator = note off" << endl;
|
//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();
|
_active_notes.pop();
|
||||||
} else if (type == CC) {
|
} else if (type == CC) {
|
||||||
//cerr << "********** MIDI Iterator = CC" << endl;
|
//cerr << "********** MIDI Iterator = CC" << endl;
|
||||||
|
|
@ -291,7 +292,7 @@ MidiModel::read(MidiRingBuffer& dst, nframes_t start, nframes_t nframes, nframes
|
||||||
|
|
||||||
|
|
||||||
bool
|
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 (iter.first->parameter().type() == MidiCCAutomation) {
|
||||||
if (ev.size() < 3)
|
if (ev.size() < 3)
|
||||||
|
|
@ -378,7 +379,7 @@ MidiModel::end_write(bool delete_stuck)
|
||||||
* and MUST be >= the latest event currently in the model.
|
* and MUST be >= the latest event currently in the model.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
MidiModel::append(const MidiEvent& ev)
|
MidiModel::append(const MIDI::Event& ev)
|
||||||
{
|
{
|
||||||
write_lock();
|
write_lock();
|
||||||
|
|
||||||
|
|
@ -643,7 +644,7 @@ MidiModel::write_to(boost::shared_ptr<MidiSource> source)
|
||||||
|
|
||||||
/* Percussive
|
/* Percussive
|
||||||
for (Notes::const_iterator n = _notes.begin(); n != _notes.end(); ++n) {
|
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);
|
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
|
// Write any pending note offs earlier than this note on
|
||||||
while ( ! active_notes.empty() ) {
|
while ( ! active_notes.empty() ) {
|
||||||
const boost::shared_ptr<const Note> earliest_off = active_notes.top();
|
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()) {
|
if (off_ev.time() <= (*n)->time()) {
|
||||||
source->append_event_unlocked(Frames, off_ev);
|
source->append_event_unlocked(Frames, off_ev);
|
||||||
active_notes.pop();
|
active_notes.pop();
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ MidiStretch::run (boost::shared_ptr<Region> r)
|
||||||
const double new_time = i->time() * _request.time_fraction;
|
const double new_time = i->time() * _request.time_fraction;
|
||||||
|
|
||||||
// FIXME: double copy
|
// FIXME: double copy
|
||||||
MidiEvent ev = MidiEvent(*i, true);
|
MIDI::Event ev = MIDI::Event(*i, true);
|
||||||
ev.time() = new_time;
|
ev.time() = new_time;
|
||||||
new_model->append(ev);
|
new_model->append(ev);
|
||||||
}
|
}
|
||||||
|
|
@ -101,7 +101,7 @@ MidiStretch::run (boost::shared_ptr<Region> r)
|
||||||
|
|
||||||
const int ret = finish (region, nsrcs, new_name);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include <sigc++/bind.h>
|
#include <sigc++/bind.h>
|
||||||
|
|
||||||
#include <pbd/enumwriter.h>
|
#include <pbd/enumwriter.h>
|
||||||
|
#include <midi++/events.h>
|
||||||
|
|
||||||
#include <ardour/midi_track.h>
|
#include <ardour/midi_track.h>
|
||||||
#include <ardour/midi_diskstream.h>
|
#include <ardour/midi_diskstream.h>
|
||||||
|
|
@ -36,7 +37,7 @@
|
||||||
#include <ardour/utils.h>
|
#include <ardour/utils.h>
|
||||||
#include <ardour/buffer_set.h>
|
#include <ardour/buffer_set.h>
|
||||||
#include <ardour/meter.h>
|
#include <ardour/meter.h>
|
||||||
#include <ardour/midi_events.h>
|
|
||||||
|
|
||||||
#include "i18n.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
|
Byte buf[3]; // CC = 3 bytes
|
||||||
buf[0] = MIDI_CMD_CONTROL;
|
buf[0] = MIDI_CMD_CONTROL;
|
||||||
MidiEvent ev(0, 3, buf, false);
|
MIDI::Event ev(0, 3, buf, false);
|
||||||
|
|
||||||
// Write track controller automation
|
// Write track controller automation
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,9 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <glibmm/miscutils.h>
|
#include <glibmm/miscutils.h>
|
||||||
|
#include <midi++/events.h>
|
||||||
|
|
||||||
#include <ardour/smf_reader.h>
|
#include <ardour/smf_reader.h>
|
||||||
#include <ardour/midi_events.h>
|
|
||||||
#include <ardour/midi_util.h>
|
#include <ardour/midi_util.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
|
||||||
|
|
@ -432,7 +432,7 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
|
||||||
assert(time >= _timeline_position);
|
assert(time >= _timeline_position);
|
||||||
time -= _timeline_position;
|
time -= _timeline_position;
|
||||||
|
|
||||||
const MidiEvent ev(time, size, buf);
|
const MIDI::Event ev(time, size, buf);
|
||||||
append_event_unlocked(Frames, ev);
|
append_event_unlocked(Frames, ev);
|
||||||
|
|
||||||
if (_model)
|
if (_model)
|
||||||
|
|
@ -452,7 +452,7 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
|
||||||
|
|
||||||
|
|
||||||
void
|
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(),
|
/*printf("%s - append chan = %u, time = %lf, size = %u, data = ", _path.c_str(),
|
||||||
(unsigned)ev.channel(), ev.time(), ev.size());
|
(unsigned)ev.channel(), ev.time(), ev.size());
|
||||||
|
|
@ -886,7 +886,7 @@ SMFSource::load_model(bool lock, bool force_reload)
|
||||||
fseek(_fd, _header_size, 0);
|
fseek(_fd, _header_size, 0);
|
||||||
|
|
||||||
uint64_t time = 0; /* in SMF ticks */
|
uint64_t time = 0; /* in SMF ticks */
|
||||||
MidiEvent ev;
|
MIDI::Event ev;
|
||||||
|
|
||||||
size_t scratch_size = 0; // keep track of scratch and minimize reallocs
|
size_t scratch_size = 0; // keep track of scratch and minimize reallocs
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,13 @@ import glob
|
||||||
Import('env libraries install_prefix')
|
Import('env libraries install_prefix')
|
||||||
|
|
||||||
midi2 = env.Copy()
|
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']:
|
if midi2['IS_OSX']:
|
||||||
midi2.Append (LINKFLAGS="-Xlinker -headerpad -Xlinker 2048")
|
midi2.Append (LINKFLAGS="-Xlinker -headerpad -Xlinker 2048")
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,15 @@ using namespace std;
|
||||||
using namespace MIDI;
|
using namespace MIDI;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
|
|
||||||
|
pthread_t JACK_MidiPort::_process_thread;
|
||||||
|
|
||||||
JACK_MidiPort::JACK_MidiPort(const XMLNode& node, jack_client_t* jack_client)
|
JACK_MidiPort::JACK_MidiPort(const XMLNode& node, jack_client_t* jack_client)
|
||||||
: Port(node)
|
: Port(node)
|
||||||
, _jack_client(jack_client)
|
, _jack_client(jack_client)
|
||||||
, _jack_input_port(NULL)
|
, _jack_input_port(NULL)
|
||||||
, _jack_output_port(NULL)
|
, _jack_output_port(NULL)
|
||||||
, _last_read_index(0)
|
, _last_read_index(0)
|
||||||
|
, non_process_thread_fifo (5 * 1024)
|
||||||
{
|
{
|
||||||
int err = create_ports (node);
|
int err = create_ports (node);
|
||||||
|
|
||||||
|
|
@ -55,23 +58,85 @@ JACK_MidiPort::cycle_start (nframes_t nframes)
|
||||||
Port::cycle_start(nframes);
|
Port::cycle_start(nframes);
|
||||||
assert(_nframes_this_cycle == nframes);
|
assert(_nframes_this_cycle == nframes);
|
||||||
_last_read_index = 0;
|
_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
|
int
|
||||||
JACK_MidiPort::write(byte * msg, size_t msglen, timestamp_t timestamp)
|
JACK_MidiPort::write(byte * msg, size_t msglen, timestamp_t timestamp)
|
||||||
{
|
{
|
||||||
if (!_currently_in_cycle) {
|
if (!is_process_thread()) {
|
||||||
error << "JACK MIDI write ignored - not in cycle ... FIX ME PAUL!" << endmsg;
|
|
||||||
return msglen;
|
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(timestamp < _nframes_this_cycle);
|
||||||
assert(_jack_output_port);
|
assert(_jack_output_port);
|
||||||
|
|
||||||
// FIXME: return value correct?
|
// FIXME: return value correct?
|
||||||
return jack_midi_event_write (
|
return jack_midi_event_write (jack_port_get_buffer (_jack_output_port, _nframes_this_cycle),
|
||||||
jack_port_get_buffer(_jack_output_port, _nframes_this_cycle),
|
|
||||||
timestamp, msg, msglen);
|
timestamp, msg, msglen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
JACK_MidiPort::flush (void* jack_port_buffer)
|
||||||
|
{
|
||||||
|
RingBuffer<Event>::rw_vector vec;
|
||||||
|
size_t written;
|
||||||
|
|
||||||
|
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
|
int
|
||||||
|
|
@ -137,3 +202,15 @@ void
|
||||||
JACK_MidiPort::set_state (const XMLNode& node)
|
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);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,19 +18,24 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ardour_midi_event_h__
|
#ifndef __libmidipp_midi_event_h__
|
||||||
#define __ardour_midi_event_h__
|
#define __libmidipp_midi_event_h__
|
||||||
|
|
||||||
#include <ardour/types.h>
|
|
||||||
#include <ardour/midi_events.h>
|
|
||||||
#include <stdint.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
|
/** If this is not defined, all methods of MidiEvent are RT safe
|
||||||
* but MidiEvent will never deep copy and (depending on the scenario)
|
* 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
|
#define MIDI_EVENT_ALLOW_ALLOC 1
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace MIDI {
|
||||||
|
|
||||||
|
|
||||||
/** Identical to jack_midi_event_t, but with double timestamp
|
/** 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
|
* time is either a frame time (from/to Jack) or a beat time (internal
|
||||||
* tempo time, used in MidiModel) depending on context.
|
* tempo time, used in MidiModel) depending on context.
|
||||||
*/
|
*/
|
||||||
struct MidiEvent {
|
struct Event {
|
||||||
#ifdef MIDI_EVENT_ALLOW_ALLOC
|
#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)
|
: _time(t)
|
||||||
, _size(s)
|
, _size(s)
|
||||||
, _buffer(b)
|
, _buffer(b)
|
||||||
, _owns_buffer(owns_buffer)
|
, _owns_buffer(owns_buffer)
|
||||||
{
|
{
|
||||||
if (owns_buffer) {
|
if (owns_buffer) {
|
||||||
_buffer = (Byte*)malloc(_size);
|
_buffer = (uint8_t*)malloc(_size);
|
||||||
if (b)
|
if (b)
|
||||||
memcpy(_buffer, b, _size);
|
memcpy(_buffer, b, _size);
|
||||||
else
|
else
|
||||||
|
|
@ -61,14 +66,14 @@ struct MidiEvent {
|
||||||
* is NOT REALTIME SAFE. Otherwise both events share a buffer and
|
* is NOT REALTIME SAFE. Otherwise both events share a buffer and
|
||||||
* memory management semantics are the caller's problem.
|
* 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)
|
: _time(copy._time)
|
||||||
, _size(copy._size)
|
, _size(copy._size)
|
||||||
, _buffer(copy._buffer)
|
, _buffer(copy._buffer)
|
||||||
, _owns_buffer(owns_buffer)
|
, _owns_buffer(owns_buffer)
|
||||||
{
|
{
|
||||||
if (owns_buffer) {
|
if (owns_buffer) {
|
||||||
_buffer = (Byte*)malloc(_size);
|
_buffer = (uint8_t*)malloc(_size);
|
||||||
if (copy._buffer)
|
if (copy._buffer)
|
||||||
memcpy(_buffer, copy._buffer, _size);
|
memcpy(_buffer, copy._buffer, _size);
|
||||||
else
|
else
|
||||||
|
|
@ -76,17 +81,17 @@ struct MidiEvent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~MidiEvent() {
|
~Event() {
|
||||||
if (_owns_buffer)
|
if (_owns_buffer)
|
||||||
free(_buffer);
|
free(_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const MidiEvent& operator=(const MidiEvent& copy) {
|
inline const Event& operator=(const Event& copy) {
|
||||||
_time = copy._time;
|
_time = copy._time;
|
||||||
if (_owns_buffer) {
|
if (_owns_buffer) {
|
||||||
if (copy._buffer) {
|
if (copy._buffer) {
|
||||||
if (!_buffer || _size < copy._size)
|
if (!_buffer || _size < copy._size)
|
||||||
_buffer = (Byte*)::realloc(_buffer, copy._size);
|
_buffer = (uint8_t*)::realloc(_buffer, copy._size);
|
||||||
memcpy(_buffer, copy._buffer, copy._size);
|
memcpy(_buffer, copy._buffer, copy._size);
|
||||||
} else {
|
} else {
|
||||||
free(_buffer);
|
free(_buffer);
|
||||||
|
|
@ -100,7 +105,22 @@ struct MidiEvent {
|
||||||
return *this;
|
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)
|
if (_time != other._time)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -117,11 +137,11 @@ struct MidiEvent {
|
||||||
return true;
|
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 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) {
|
if (_owns_buffer) {
|
||||||
free(_buffer);
|
free(_buffer);
|
||||||
_buffer = NULL;
|
_buffer = NULL;
|
||||||
|
|
@ -132,12 +152,12 @@ struct MidiEvent {
|
||||||
|
|
||||||
inline void realloc(size_t size) {
|
inline void realloc(size_t size) {
|
||||||
assert(_owns_buffer);
|
assert(_owns_buffer);
|
||||||
_buffer = (Byte*) ::realloc(_buffer, size);
|
_buffer = (uint8_t*) ::realloc(_buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
inline void set_buffer(Byte* buf) { _buffer = buf; }
|
inline void set_buffer(uint8_t* buf) { _buffer = buf; }
|
||||||
|
|
||||||
#endif // MIDI_EVENT_ALLOW_ALLOC
|
#endif // MIDI_EVENT_ALLOW_ALLOC
|
||||||
|
|
||||||
|
|
@ -155,13 +175,13 @@ struct MidiEvent {
|
||||||
inline uint8_t velocity() const { return (_buffer[2]); }
|
inline uint8_t velocity() const { return (_buffer[2]); }
|
||||||
inline uint8_t cc_number() const { return (_buffer[1]); }
|
inline uint8_t cc_number() const { return (_buffer[1]); }
|
||||||
inline uint8_t cc_value() const { return (_buffer[2]); }
|
inline uint8_t cc_value() const { return (_buffer[2]); }
|
||||||
inline const Byte* buffer() const { return _buffer; }
|
inline const uint8_t* buffer() const { return _buffer; }
|
||||||
inline Byte*& buffer() { return _buffer; }
|
inline uint8_t*& buffer() { return _buffer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double _time; /**< Sample index (or beat time) at which event is valid */
|
double _time; /**< Sample index (or beat time) at which event is valid */
|
||||||
uint32_t _size; /**< Number of bytes of data in \a buffer */
|
uint32_t _size; /**< Number of uint8_ts of data in \a buffer */
|
||||||
Byte* _buffer; /**< Raw MIDI data */
|
uint8_t* _buffer; /**< Raw MIDI data */
|
||||||
|
|
||||||
#ifdef MIDI_EVENT_ALLOW_ALLOC
|
#ifdef MIDI_EVENT_ALLOW_ALLOC
|
||||||
bool _owns_buffer; /**< Whether buffer is locally allocated */
|
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__ */
|
||||||
|
|
@ -28,9 +28,13 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <glibmm/thread.h>
|
||||||
|
|
||||||
|
#include <pbd/ringbuffer.h>
|
||||||
#include <jack/jack.h>
|
#include <jack/jack.h>
|
||||||
#include <jack/midiport.h>
|
#include <jack/midiport.h>
|
||||||
#include <midi++/port.h>
|
#include <midi++/port.h>
|
||||||
|
#include <midi++/event.h>
|
||||||
|
|
||||||
namespace MIDI
|
namespace MIDI
|
||||||
{
|
{
|
||||||
|
|
@ -52,6 +56,8 @@ public:
|
||||||
virtual XMLNode& get_state () const;
|
virtual XMLNode& get_state () const;
|
||||||
virtual void set_state (const XMLNode&);
|
virtual void set_state (const XMLNode&);
|
||||||
|
|
||||||
|
static void set_process_thread (pthread_t);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string get_typestring () const {
|
std::string get_typestring () const {
|
||||||
return typestring;
|
return typestring;
|
||||||
|
|
@ -69,6 +75,14 @@ private:
|
||||||
jack_port_t* _jack_input_port;
|
jack_port_t* _jack_input_port;
|
||||||
jack_port_t* _jack_output_port;
|
jack_port_t* _jack_output_port;
|
||||||
nframes_t _last_read_index;
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue