#include <ardour/midi_source.h>
#include <ardour/midi_diskstream.h>
#include <ardour/midi_track.h>
-#include <ardour/midi_events.h>
#include <ardour/smf_source.h>
#include <ardour/region_factory.h>
#include <ardour/midi_region.h>
#include <ardour/midi_source.h>
#include <ardour/midi_diskstream.h>
-#include <ardour/midi_events.h>
#include <ardour/midi_model.h>
#include "streamview.h"
#include <ardour/midi_source.h>
#include <ardour/midi_diskstream.h>
#include <ardour/midi_track.h>
-#include <ardour/midi_events.h>
#include <ardour/smf_source.h>
#include <ardour/region_factory.h>
#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 {
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);
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; }
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; }
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
/* 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.
};
+++ /dev/null
-/*
- Copyright (C) 2007 Paul Davis
- Author: Dave Robillard
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef __ardour_midi_event_h__
-#define __ardour_midi_event_h__
-
-#include <ardour/types.h>
-#include <ardour/midi_events.h>
-#include <stdint.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. */
-#define MIDI_EVENT_ALLOW_ALLOC 1
-
-namespace ARDOUR {
-
-
-/** Identical to jack_midi_event_t, but with double timestamp
- *
- * time is either a frame time (from/to Jack) or a beat time (internal
- * tempo time, used in MidiModel) depending on context.
- */
-struct MidiEvent {
-#ifdef MIDI_EVENT_ALLOW_ALLOC
- MidiEvent(double t=0, uint32_t s=0, Byte* b=NULL, bool owns_buffer=false)
- : _time(t)
- , _size(s)
- , _buffer(b)
- , _owns_buffer(owns_buffer)
- {
- if (owns_buffer) {
- _buffer = (Byte*)malloc(_size);
- if (b)
- memcpy(_buffer, b, _size);
- else
- memset(_buffer, 0, _size);
- }
- }
-
- /** Copy \a copy.
- *
- * If \a owns_buffer is true, the buffer will be copied and this method
- * 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)
- : _time(copy._time)
- , _size(copy._size)
- , _buffer(copy._buffer)
- , _owns_buffer(owns_buffer)
- {
- if (owns_buffer) {
- _buffer = (Byte*)malloc(_size);
- if (copy._buffer)
- memcpy(_buffer, copy._buffer, _size);
- else
- memset(_buffer, 0, _size);
- }
- }
-
- ~MidiEvent() {
- if (_owns_buffer)
- free(_buffer);
- }
-
- inline const MidiEvent& operator=(const MidiEvent& copy) {
- _time = copy._time;
- if (_owns_buffer) {
- if (copy._buffer) {
- if (!_buffer || _size < copy._size)
- _buffer = (Byte*)::realloc(_buffer, copy._size);
- memcpy(_buffer, copy._buffer, copy._size);
- } else {
- free(_buffer);
- _buffer = NULL;
- }
- } else {
- _buffer = copy._buffer;
- }
-
- _size = copy._size;
- return *this;
- }
-
- inline bool operator==(const MidiEvent& other) const {
- if (_time != other._time)
- return false;
-
- if (_size != other._size)
- return false;
-
- if (_buffer == other._buffer)
- return true;
-
- for (size_t i=0; i < _size; ++i)
- if (_buffer[i] != other._buffer[i])
- return false;
-
- return true;
- }
-
- inline bool operator!=(const MidiEvent& other) const { return ! operator==(other); }
-
- inline bool owns_buffer() const { return _owns_buffer; }
-
- inline void set_buffer(Byte* buf, bool own) {
- if (_owns_buffer) {
- free(_buffer);
- _buffer = NULL;
- }
- _buffer = buf;
- _owns_buffer = own;
- }
-
- inline void realloc(size_t size) {
- assert(_owns_buffer);
- _buffer = (Byte*) ::realloc(_buffer, size);
- }
-
-#else
-
- inline void set_buffer(Byte* buf) { _buffer = buf; }
-
-#endif // MIDI_EVENT_ALLOW_ALLOC
-
- inline double time() const { return _time; }
- inline double& time() { return _time; }
- inline uint32_t size() const { return _size; }
- 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() 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; }
-
-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 */
-
-#ifdef MIDI_EVENT_ALLOW_ALLOC
- bool _owns_buffer; /**< Whether buffer is locally allocated */
-#endif
-};
-
-
-} // namespace ARDOUR
-
-#endif /* __ardour_midi_event_h__ */
+++ /dev/null
-/* Definitions to ease working with raw MIDI.
- *
- * Adapted from ALSA's asounddef.h
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef MIDI_H
-#define MIDI_H
-
-
-/**
- * \defgroup midi MIDI Definitions
- * MIDI command and controller number definitions.
- * \{
- */
-
-// Commands:
-
-#define MIDI_CMD_NOTE_OFF 0x80 /**< note off */
-#define MIDI_CMD_NOTE_ON 0x90 /**< note on */
-#define MIDI_CMD_NOTE_PRESSURE 0xA0 /**< key pressure */
-#define MIDI_CMD_CONTROL 0xB0 /**< control change */
-#define MIDI_CMD_PGM_CHANGE 0xC0 /**< program change */
-#define MIDI_CMD_CHANNEL_PRESSURE 0xD0 /**< channel pressure */
-#define MIDI_CMD_BENDER 0xE0 /**< pitch bender */
-
-#define MIDI_CMD_COMMON_SYSEX 0xF0 /**< sysex (system exclusive) begin */
-#define MIDI_CMD_COMMON_MTC_QUARTER 0xF1 /**< MTC quarter frame */
-#define MIDI_CMD_COMMON_SONG_POS 0xF2 /**< song position */
-#define MIDI_CMD_COMMON_SONG_SELECT 0xF3 /**< song select */
-#define MIDI_CMD_COMMON_TUNE_REQUEST 0xF6 /**< tune request */
-#define MIDI_CMD_COMMON_SYSEX_END 0xF7 /**< end of sysex */
-#define MIDI_CMD_COMMON_CLOCK 0xF8 /**< clock */
-#define MIDI_CMD_COMMON_TICK 0xF9 /**< tick */
-#define MIDI_CMD_COMMON_START 0xFA /**< start */
-#define MIDI_CMD_COMMON_CONTINUE 0xFB /**< continue */
-#define MIDI_CMD_COMMON_STOP 0xFC /**< stop */
-#define MIDI_CMD_COMMON_SENSING 0xFE /**< active sensing */
-#define MIDI_CMD_COMMON_RESET 0xFF /**< reset */
-
-
-// Controllers:
-
-#define MIDI_CTL_MSB_BANK 0x00 /**< Bank selection */
-#define MIDI_CTL_MSB_MODWHEEL 0x01 /**< Modulation */
-#define MIDI_CTL_MSB_BREATH 0x02 /**< Breath */
-#define MIDI_CTL_MSB_FOOT 0x04 /**< Foot */
-#define MIDI_CTL_MSB_PORTAMENTO_TIME 0x05 /**< Portamento time */
-#define MIDI_CTL_MSB_DATA_ENTRY 0x06 /**< Data entry */
-#define MIDI_CTL_MSB_MAIN_VOLUME 0x07 /**< Main volume */
-#define MIDI_CTL_MSB_BALANCE 0x08 /**< Balance */
-#define MIDI_CTL_MSB_PAN 0x0A /**< Panpot */
-#define MIDI_CTL_MSB_EXPRESSION 0x0B /**< Expression */
-#define MIDI_CTL_MSB_EFFECT1 0x0C /**< Effect1 */
-#define MIDI_CTL_MSB_EFFECT2 0x0D /**< Effect2 */
-#define MIDI_CTL_MSB_GENERAL_PURPOSE1 0x10 /**< General purpose 1 */
-#define MIDI_CTL_MSB_GENERAL_PURPOSE2 0x11 /**< General purpose 2 */
-#define MIDI_CTL_MSB_GENERAL_PURPOSE3 0x12 /**< General purpose 3 */
-#define MIDI_CTL_MSB_GENERAL_PURPOSE4 0x13 /**< General purpose 4 */
-#define MIDI_CTL_LSB_BANK 0x20 /**< Bank selection */
-#define MIDI_CTL_LSB_MODWHEEL 0x21 /**< Modulation */
-#define MIDI_CTL_LSB_BREATH 0x22 /**< Breath */
-#define MIDI_CTL_LSB_FOOT 0x24 /**< Foot */
-#define MIDI_CTL_LSB_PORTAMENTO_TIME 0x25 /**< Portamento time */
-#define MIDI_CTL_LSB_DATA_ENTRY 0x26 /**< Data entry */
-#define MIDI_CTL_LSB_MAIN_VOLUME 0x27 /**< Main volume */
-#define MIDI_CTL_LSB_BALANCE 0x28 /**< Balance */
-#define MIDI_CTL_LSB_PAN 0x2A /**< Panpot */
-#define MIDI_CTL_LSB_EXPRESSION 0x2B /**< Expression */
-#define MIDI_CTL_LSB_EFFECT1 0x2C /**< Effect1 */
-#define MIDI_CTL_LSB_EFFECT2 0x2D /**< Effect2 */
-#define MIDI_CTL_LSB_GENERAL_PURPOSE1 0x30 /**< General purpose 1 */
-#define MIDI_CTL_LSB_GENERAL_PURPOSE2 0x31 /**< General purpose 2 */
-#define MIDI_CTL_LSB_GENERAL_PURPOSE3 0x32 /**< General purpose 3 */
-#define MIDI_CTL_LSB_GENERAL_PURPOSE4 0x33 /**< General purpose 4 */
-#define MIDI_CTL_SUSTAIN 0x40 /**< Sustain pedal */
-#define MIDI_CTL_PORTAMENTO 0x41 /**< Portamento */
-#define MIDI_CTL_SOSTENUTO 0x42 /**< Sostenuto */
-#define MIDI_CTL_SUSTENUTO 0x42 /**< Sostenuto (a typo in the older version) */
-#define MIDI_CTL_SOFT_PEDAL 0x43 /**< Soft pedal */
-#define MIDI_CTL_LEGATO_FOOTSWITCH 0x44 /**< Legato foot switch */
-#define MIDI_CTL_HOLD2 0x45 /**< Hold2 */
-#define MIDI_CTL_SC1_SOUND_VARIATION 0x46 /**< SC1 Sound Variation */
-#define MIDI_CTL_SC2_TIMBRE 0x47 /**< SC2 Timbre */
-#define MIDI_CTL_SC3_RELEASE_TIME 0x48 /**< SC3 Release Time */
-#define MIDI_CTL_SC4_ATTACK_TIME 0x49 /**< SC4 Attack Time */
-#define MIDI_CTL_SC5_BRIGHTNESS 0x4A /**< SC5 Brightness */
-#define MIDI_CTL_SC6 0x4B /**< SC6 */
-#define MIDI_CTL_SC7 0x4C /**< SC7 */
-#define MIDI_CTL_SC8 0x4D /**< SC8 */
-#define MIDI_CTL_SC9 0x4E /**< SC9 */
-#define MIDI_CTL_SC10 0x4F /**< SC10 */
-#define MIDI_CTL_GENERAL_PURPOSE5 0x50 /**< General purpose 5 */
-#define MIDI_CTL_GENERAL_PURPOSE6 0x51 /**< General purpose 6 */
-#define MIDI_CTL_GENERAL_PURPOSE7 0x52 /**< General purpose 7 */
-#define MIDI_CTL_GENERAL_PURPOSE8 0x53 /**< General purpose 8 */
-#define MIDI_CTL_PORTAMENTO_CONTROL 0x54 /**< Portamento control */
-#define MIDI_CTL_E1_REVERB_DEPTH 0x5B /**< E1 Reverb Depth */
-#define MIDI_CTL_E2_TREMOLO_DEPTH 0x5C /**< E2 Tremolo Depth */
-#define MIDI_CTL_E3_CHORUS_DEPTH 0x5D /**< E3 Chorus Depth */
-#define MIDI_CTL_E4_DETUNE_DEPTH 0x5E /**< E4 Detune Depth */
-#define MIDI_CTL_E5_PHASER_DEPTH 0x5F /**< E5 Phaser Depth */
-#define MIDI_CTL_DATA_INCREMENT 0x60 /**< Data Increment */
-#define MIDI_CTL_DATA_DECREMENT 0x61 /**< Data Decrement */
-#define MIDI_CTL_NONREG_PARM_NUM_LSB 0x62 /**< Non-registered parameter number */
-#define MIDI_CTL_NONREG_PARM_NUM_MSB 0x63 /**< Non-registered parameter number */
-#define MIDI_CTL_REGIST_PARM_NUM_LSB 0x64 /**< Registered parameter number */
-#define MIDI_CTL_REGIST_PARM_NUM_MSB 0x65 /**< Registered parameter number */
-#define MIDI_CTL_ALL_SOUNDS_OFF 0x78 /**< All sounds off */
-#define MIDI_CTL_RESET_CONTROLLERS 0x79 /**< Reset Controllers */
-#define MIDI_CTL_LOCAL_CONTROL_SWITCH 0x7A /**< Local control switch */
-#define MIDI_CTL_ALL_NOTES_OFF 0x7B /**< All notes off */
-#define MIDI_CTL_OMNI_OFF 0x7C /**< Omni off */
-#define MIDI_CTL_OMNI_ON 0x7D /**< Omni on */
-#define MIDI_CTL_MONO1 0x7E /**< Mono1 */
-#define MIDI_CTL_MONO2 0x7F /**< Mono2 */
-//@}
-
-
-/** \} */
-
-#endif /* MIDI_H */
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]; }
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;
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> >,
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;
if (read_space() == 0)
return 0;
- MidiEvent ev;
+ MIDI::Event ev;
size_t count = 0;
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);
#ifndef __ardour_midi_util_h__
#define __ardour_midi_util_h__
-#include <ardour/midi_events.h>
+#include <midi++/events.h>
namespace ARDOUR {
#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 {
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;
};
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 ();
#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>
*/
PBD::ThreadCreatedWithRequestSize (pthread_self(), X_("Audioengine"), 4096);
+ MIDI::JACK_MidiPort::set_process_thread (pthread_self());
}
int
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)
{
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;
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);
// 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);
_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);
// 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);
* @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;
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;
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);
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;
}
#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>
}
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;
}
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;
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)
* and MUST be >= the latest event currently in the model.
*/
void
-MidiModel::append(const MidiEvent& ev)
+MidiModel::append(const MIDI::Event& ev)
{
write_lock();
/* 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);
}*/
// 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();
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);
}
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;
}
#include <sigc++/bind.h>
#include <pbd/enumwriter.h>
+#include <midi++/events.h>
#include <ardour/midi_track.h>
#include <ardour/midi_diskstream.h>
#include <ardour/utils.h>
#include <ardour/buffer_set.h>
#include <ardour/meter.h>
-#include <ardour/midi_events.h>
+
#include "i18n.h"
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
#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;
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)
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());
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
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")
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);
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
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);
+}
--- /dev/null
+/*
+ Copyright (C) 2007 Paul Davis
+ Author: Dave Robillard
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __libmidipp_midi_event_h__
+#define __libmidipp_midi_event_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.
+ */
+#define MIDI_EVENT_ALLOW_ALLOC 1
+
+namespace MIDI {
+
+
+/** Identical to jack_midi_event_t, but with double timestamp
+ *
+ * time is either a frame time (from/to Jack) or a beat time (internal
+ * tempo time, used in MidiModel) depending on context.
+ */
+struct Event {
+#ifdef MIDI_EVENT_ALLOW_ALLOC
+ 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 = (uint8_t*)malloc(_size);
+ if (b)
+ memcpy(_buffer, b, _size);
+ else
+ memset(_buffer, 0, _size);
+ }
+ }
+
+ /** Copy \a copy.
+ *
+ * If \a owns_buffer is true, the buffer will be copied and this method
+ * is NOT REALTIME SAFE. Otherwise both events share a buffer and
+ * memory management semantics are the caller's problem.
+ */
+ Event(const Event& copy, bool owns_buffer)
+ : _time(copy._time)
+ , _size(copy._size)
+ , _buffer(copy._buffer)
+ , _owns_buffer(owns_buffer)
+ {
+ if (owns_buffer) {
+ _buffer = (uint8_t*)malloc(_size);
+ if (copy._buffer)
+ memcpy(_buffer, copy._buffer, _size);
+ else
+ memset(_buffer, 0, _size);
+ }
+ }
+
+ ~Event() {
+ if (_owns_buffer)
+ free(_buffer);
+ }
+
+ inline const Event& operator=(const Event& copy) {
+ _time = copy._time;
+ if (_owns_buffer) {
+ if (copy._buffer) {
+ if (!_buffer || _size < copy._size)
+ _buffer = (uint8_t*)::realloc(_buffer, copy._size);
+ memcpy(_buffer, copy._buffer, copy._size);
+ } else {
+ free(_buffer);
+ _buffer = NULL;
+ }
+ } else {
+ _buffer = copy._buffer;
+ }
+
+ _size = copy._size;
+ return *this;
+ }
+
+ 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;
+
+ if (_size != other._size)
+ return false;
+
+ if (_buffer == other._buffer)
+ return true;
+
+ for (size_t i=0; i < _size; ++i)
+ if (_buffer[i] != other._buffer[i])
+ return false;
+
+ return true;
+ }
+
+ inline bool operator!=(const Event& other) const { return ! operator==(other); }
+
+ inline bool owns_buffer() const { return _owns_buffer; }
+
+ inline void set_buffer(uint8_t* buf, bool own) {
+ if (_owns_buffer) {
+ free(_buffer);
+ _buffer = NULL;
+ }
+ _buffer = buf;
+ _owns_buffer = own;
+ }
+
+ inline void realloc(size_t size) {
+ assert(_owns_buffer);
+ _buffer = (uint8_t*) ::realloc(_buffer, size);
+ }
+
+#else
+
+ inline void set_buffer(uint8_t* buf) { _buffer = buf; }
+
+#endif // MIDI_EVENT_ALLOW_ALLOC
+
+ inline double time() const { return _time; }
+ inline double& time() { return _time; }
+ inline uint32_t size() const { return _size; }
+ 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() 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 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 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 */
+#endif
+};
+
+
+}
+
+#endif /* __libmidipp_midi_event_h__ */
--- /dev/null
+/* Definitions to ease working with raw MIDI.
+ *
+ * Adapted from ALSA's asounddef.h
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef MIDI_H
+#define MIDI_H
+
+
+/**
+ * \defgroup midi MIDI Definitions
+ * MIDI command and controller number definitions.
+ * \{
+ */
+
+// Commands:
+
+#define MIDI_CMD_NOTE_OFF 0x80 /**< note off */
+#define MIDI_CMD_NOTE_ON 0x90 /**< note on */
+#define MIDI_CMD_NOTE_PRESSURE 0xA0 /**< key pressure */
+#define MIDI_CMD_CONTROL 0xB0 /**< control change */
+#define MIDI_CMD_PGM_CHANGE 0xC0 /**< program change */
+#define MIDI_CMD_CHANNEL_PRESSURE 0xD0 /**< channel pressure */
+#define MIDI_CMD_BENDER 0xE0 /**< pitch bender */
+
+#define MIDI_CMD_COMMON_SYSEX 0xF0 /**< sysex (system exclusive) begin */
+#define MIDI_CMD_COMMON_MTC_QUARTER 0xF1 /**< MTC quarter frame */
+#define MIDI_CMD_COMMON_SONG_POS 0xF2 /**< song position */
+#define MIDI_CMD_COMMON_SONG_SELECT 0xF3 /**< song select */
+#define MIDI_CMD_COMMON_TUNE_REQUEST 0xF6 /**< tune request */
+#define MIDI_CMD_COMMON_SYSEX_END 0xF7 /**< end of sysex */
+#define MIDI_CMD_COMMON_CLOCK 0xF8 /**< clock */
+#define MIDI_CMD_COMMON_TICK 0xF9 /**< tick */
+#define MIDI_CMD_COMMON_START 0xFA /**< start */
+#define MIDI_CMD_COMMON_CONTINUE 0xFB /**< continue */
+#define MIDI_CMD_COMMON_STOP 0xFC /**< stop */
+#define MIDI_CMD_COMMON_SENSING 0xFE /**< active sensing */
+#define MIDI_CMD_COMMON_RESET 0xFF /**< reset */
+
+
+// Controllers:
+
+#define MIDI_CTL_MSB_BANK 0x00 /**< Bank selection */
+#define MIDI_CTL_MSB_MODWHEEL 0x01 /**< Modulation */
+#define MIDI_CTL_MSB_BREATH 0x02 /**< Breath */
+#define MIDI_CTL_MSB_FOOT 0x04 /**< Foot */
+#define MIDI_CTL_MSB_PORTAMENTO_TIME 0x05 /**< Portamento time */
+#define MIDI_CTL_MSB_DATA_ENTRY 0x06 /**< Data entry */
+#define MIDI_CTL_MSB_MAIN_VOLUME 0x07 /**< Main volume */
+#define MIDI_CTL_MSB_BALANCE 0x08 /**< Balance */
+#define MIDI_CTL_MSB_PAN 0x0A /**< Panpot */
+#define MIDI_CTL_MSB_EXPRESSION 0x0B /**< Expression */
+#define MIDI_CTL_MSB_EFFECT1 0x0C /**< Effect1 */
+#define MIDI_CTL_MSB_EFFECT2 0x0D /**< Effect2 */
+#define MIDI_CTL_MSB_GENERAL_PURPOSE1 0x10 /**< General purpose 1 */
+#define MIDI_CTL_MSB_GENERAL_PURPOSE2 0x11 /**< General purpose 2 */
+#define MIDI_CTL_MSB_GENERAL_PURPOSE3 0x12 /**< General purpose 3 */
+#define MIDI_CTL_MSB_GENERAL_PURPOSE4 0x13 /**< General purpose 4 */
+#define MIDI_CTL_LSB_BANK 0x20 /**< Bank selection */
+#define MIDI_CTL_LSB_MODWHEEL 0x21 /**< Modulation */
+#define MIDI_CTL_LSB_BREATH 0x22 /**< Breath */
+#define MIDI_CTL_LSB_FOOT 0x24 /**< Foot */
+#define MIDI_CTL_LSB_PORTAMENTO_TIME 0x25 /**< Portamento time */
+#define MIDI_CTL_LSB_DATA_ENTRY 0x26 /**< Data entry */
+#define MIDI_CTL_LSB_MAIN_VOLUME 0x27 /**< Main volume */
+#define MIDI_CTL_LSB_BALANCE 0x28 /**< Balance */
+#define MIDI_CTL_LSB_PAN 0x2A /**< Panpot */
+#define MIDI_CTL_LSB_EXPRESSION 0x2B /**< Expression */
+#define MIDI_CTL_LSB_EFFECT1 0x2C /**< Effect1 */
+#define MIDI_CTL_LSB_EFFECT2 0x2D /**< Effect2 */
+#define MIDI_CTL_LSB_GENERAL_PURPOSE1 0x30 /**< General purpose 1 */
+#define MIDI_CTL_LSB_GENERAL_PURPOSE2 0x31 /**< General purpose 2 */
+#define MIDI_CTL_LSB_GENERAL_PURPOSE3 0x32 /**< General purpose 3 */
+#define MIDI_CTL_LSB_GENERAL_PURPOSE4 0x33 /**< General purpose 4 */
+#define MIDI_CTL_SUSTAIN 0x40 /**< Sustain pedal */
+#define MIDI_CTL_PORTAMENTO 0x41 /**< Portamento */
+#define MIDI_CTL_SOSTENUTO 0x42 /**< Sostenuto */
+#define MIDI_CTL_SUSTENUTO 0x42 /**< Sostenuto (a typo in the older version) */
+#define MIDI_CTL_SOFT_PEDAL 0x43 /**< Soft pedal */
+#define MIDI_CTL_LEGATO_FOOTSWITCH 0x44 /**< Legato foot switch */
+#define MIDI_CTL_HOLD2 0x45 /**< Hold2 */
+#define MIDI_CTL_SC1_SOUND_VARIATION 0x46 /**< SC1 Sound Variation */
+#define MIDI_CTL_SC2_TIMBRE 0x47 /**< SC2 Timbre */
+#define MIDI_CTL_SC3_RELEASE_TIME 0x48 /**< SC3 Release Time */
+#define MIDI_CTL_SC4_ATTACK_TIME 0x49 /**< SC4 Attack Time */
+#define MIDI_CTL_SC5_BRIGHTNESS 0x4A /**< SC5 Brightness */
+#define MIDI_CTL_SC6 0x4B /**< SC6 */
+#define MIDI_CTL_SC7 0x4C /**< SC7 */
+#define MIDI_CTL_SC8 0x4D /**< SC8 */
+#define MIDI_CTL_SC9 0x4E /**< SC9 */
+#define MIDI_CTL_SC10 0x4F /**< SC10 */
+#define MIDI_CTL_GENERAL_PURPOSE5 0x50 /**< General purpose 5 */
+#define MIDI_CTL_GENERAL_PURPOSE6 0x51 /**< General purpose 6 */
+#define MIDI_CTL_GENERAL_PURPOSE7 0x52 /**< General purpose 7 */
+#define MIDI_CTL_GENERAL_PURPOSE8 0x53 /**< General purpose 8 */
+#define MIDI_CTL_PORTAMENTO_CONTROL 0x54 /**< Portamento control */
+#define MIDI_CTL_E1_REVERB_DEPTH 0x5B /**< E1 Reverb Depth */
+#define MIDI_CTL_E2_TREMOLO_DEPTH 0x5C /**< E2 Tremolo Depth */
+#define MIDI_CTL_E3_CHORUS_DEPTH 0x5D /**< E3 Chorus Depth */
+#define MIDI_CTL_E4_DETUNE_DEPTH 0x5E /**< E4 Detune Depth */
+#define MIDI_CTL_E5_PHASER_DEPTH 0x5F /**< E5 Phaser Depth */
+#define MIDI_CTL_DATA_INCREMENT 0x60 /**< Data Increment */
+#define MIDI_CTL_DATA_DECREMENT 0x61 /**< Data Decrement */
+#define MIDI_CTL_NONREG_PARM_NUM_LSB 0x62 /**< Non-registered parameter number */
+#define MIDI_CTL_NONREG_PARM_NUM_MSB 0x63 /**< Non-registered parameter number */
+#define MIDI_CTL_REGIST_PARM_NUM_LSB 0x64 /**< Registered parameter number */
+#define MIDI_CTL_REGIST_PARM_NUM_MSB 0x65 /**< Registered parameter number */
+#define MIDI_CTL_ALL_SOUNDS_OFF 0x78 /**< All sounds off */
+#define MIDI_CTL_RESET_CONTROLLERS 0x79 /**< Reset Controllers */
+#define MIDI_CTL_LOCAL_CONTROL_SWITCH 0x7A /**< Local control switch */
+#define MIDI_CTL_ALL_NOTES_OFF 0x7B /**< All notes off */
+#define MIDI_CTL_OMNI_OFF 0x7C /**< Omni off */
+#define MIDI_CTL_OMNI_ON 0x7D /**< Omni on */
+#define MIDI_CTL_MONO1 0x7E /**< Mono1 */
+#define MIDI_CTL_MONO2 0x7F /**< Mono2 */
+//@}
+
+
+/** \} */
+
+#endif /* MIDI_H */
#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
{
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;
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;
};