X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fmidi_port.cc;h=55280eb9428e82aed7fc611a53d866991f0b0b82;hb=70308f51747b5beeff99dec9f10490080f00b0c2;hp=50d4ce64e83f784675136e42db080bd143c018af;hpb=0938a42440cc82ce8d0cb064840c258c863714ab;p=ardour.git diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc index 50d4ce64e8..55280eb942 100644 --- a/libs/ardour/midi_port.cc +++ b/libs/ardour/midi_port.cc @@ -26,11 +26,14 @@ using namespace ARDOUR; using namespace std; -MidiPort::MidiPort (const std::string& name, Flags flags) +#define port_engine AudioEngine::instance()->port_engine() + +MidiPort::MidiPort (const std::string& name, PortFlags flags) : Port (name, DataType::MIDI, flags) , _has_been_mixed_down (false) , _resolve_required (false) , _input_active (true) + , _always_parse (false) { _buffer = new MidiBuffer (AudioEngine::instance()->raw_buffer_size (DataType::MIDI)); } @@ -43,14 +46,32 @@ MidiPort::~MidiPort() void MidiPort::cycle_start (pframes_t nframes) { + framepos_t now = AudioEngine::instance()->sample_time_at_cycle_start(); + Port::cycle_start (nframes); _buffer->clear (); - assert (_buffer->size () == 0); - if (sends_output ()) { - jack_midi_clear_buffer (jack_port_get_buffer (_jack_port, nframes)); + port_engine.midi_clear (port_engine.get_buffer (_port_handle, nframes)); + } + + if (_always_parse) { + MidiBuffer& mb (get_midi_buffer (nframes)); + + /* dump incoming MIDI to parser */ + + for (MidiBuffer::iterator b = mb.begin(); b != mb.end(); ++b) { + uint8_t* buf = (*b).buffer(); + + _self_parser.set_timestamp (now + (*b).time()); + + uint32_t limit = (*b).size(); + + for (size_t n = 0; n < limit; ++n) { + _self_parser.scanner (buf[n]); + } + } } } @@ -65,33 +86,33 @@ MidiPort::get_midi_buffer (pframes_t nframes) if (_input_active) { - void* jack_buffer = jack_port_get_buffer (_jack_port, nframes); - const pframes_t event_count = jack_midi_get_event_count (jack_buffer); - - assert (event_count < _buffer->capacity()); - - /* suck all relevant MIDI events from the JACK MIDI port buffer + void* buffer = port_engine.get_buffer (_port_handle, nframes); + const pframes_t event_count = port_engine.get_midi_event_count (buffer); + + /* suck all relevant MIDI events from the MIDI port buffer into our MidiBuffer */ - + for (pframes_t i = 0; i < event_count; ++i) { - jack_midi_event_t ev; + pframes_t timestamp; + size_t size; + uint8_t* buf; - jack_midi_event_get (&ev, jack_buffer, i); + port_engine.midi_event_get (timestamp, size, &buf, buffer, i); - if (ev.buffer[0] == 0xfe) { + if (buf[0] == 0xfe) { /* throw away active sensing */ continue; } /* check that the event is in the acceptable time range */ - if ((ev.time >= (_global_port_buffer_offset + _port_buffer_offset)) && - (ev.time < (_global_port_buffer_offset + _port_buffer_offset + nframes))) { - _buffer->push_back (ev); + if ((timestamp >= (_global_port_buffer_offset + _port_buffer_offset)) && + (timestamp < (_global_port_buffer_offset + _port_buffer_offset + nframes))) { + _buffer->push_back (timestamp, size, buf); } else { - cerr << "Dropping incoming MIDI at time " << ev.time << "; offset=" + cerr << "Dropping incoming MIDI at time " << timestamp << "; offset=" << _global_port_buffer_offset << " limit=" << (_global_port_buffer_offset + _port_buffer_offset + nframes) << "\n"; } @@ -112,7 +133,6 @@ MidiPort::get_midi_buffer (pframes_t nframes) return *_buffer; } - void MidiPort::cycle_end (pframes_t /*nframes*/) { @@ -126,45 +146,49 @@ MidiPort::cycle_split () } void -MidiPort::resolve_notes (void* jack_buffer, MidiBuffer::TimeType when) +MidiPort::resolve_notes (void* port_buffer, MidiBuffer::TimeType when) { - uint8_t ev[3]; - - ev[2] = 0; - for (uint8_t channel = 0; channel <= 0xF; channel++) { - ev[0] = (MIDI_CMD_CONTROL | channel); + + uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 }; /* we need to send all notes off AND turn the * sustain/damper pedal off to handle synths * that prioritize sustain over AllNotesOff */ - ev[1] = MIDI_CTL_SUSTAIN; - - if (jack_midi_event_write (jack_buffer, when, ev, 3) != 0) { - cerr << "failed to deliver sustain-zero on channel " << channel << " on port " << name() << endl; + if (port_engine.midi_event_put (port_buffer, when, ev, 3) != 0) { + cerr << "failed to deliver sustain-zero on channel " << (int)channel << " on port " << name() << endl; } ev[1] = MIDI_CTL_ALL_NOTES_OFF; - if (jack_midi_event_write (jack_buffer, 0, ev, 3) != 0) { - cerr << "failed to deliver ALL NOTES OFF on channel " << channel << " on port " << name() << endl; + if (port_engine.midi_event_put (port_buffer, 0, ev, 3) != 0) { + cerr << "failed to deliver ALL NOTES OFF on channel " << (int)channel << " on port " << name() << endl; } } } void -MidiPort::flush_buffers (pframes_t nframes, framepos_t /*time*/) +MidiPort::flush_buffers (pframes_t nframes) { if (sends_output ()) { - void* jack_buffer = jack_port_get_buffer (_jack_port, nframes); - + void* port_buffer = 0; + if (_resolve_required) { + port_buffer = port_engine.get_buffer (_port_handle, nframes); /* resolve all notes at the start of the buffer */ - resolve_notes (jack_buffer, 0); - _resolve_required= false; + resolve_notes (port_buffer, 0); + _resolve_required = false; + } + + if (_buffer->empty()) { + return; + } + + if (!port_buffer) { + port_buffer = port_engine.get_buffer (_port_handle, nframes); } for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) { @@ -175,24 +199,31 @@ MidiPort::flush_buffers (pframes_t nframes, framepos_t /*time*/) assert (ev.time() < (nframes + _global_port_buffer_offset + _port_buffer_offset)); - if (ev.event_type() == LoopEventType) { - resolve_notes (jack_buffer, ev.time()); - continue; - } - if (ev.time() >= _global_port_buffer_offset + _port_buffer_offset) { - if (jack_midi_event_write (jack_buffer, (jack_nframes_t) ev.time(), ev.buffer(), ev.size()) != 0) { + if (port_engine.midi_event_put (port_buffer, (pframes_t) ev.time(), ev.buffer(), ev.size()) != 0) { cerr << "write failed, drop flushed note off on the floor, time " << ev.time() << " > " << _global_port_buffer_offset + _port_buffer_offset << endl; } } else { cerr << "drop flushed event on the floor, time " << ev.time() - << " < " << _global_port_buffer_offset + _port_buffer_offset << endl; + << " to early for " << _global_port_buffer_offset + << " + " << _port_buffer_offset << endl; } } + + /* done.. the data has moved to the port buffer, mark it so + */ + + _buffer->clear (); } } +void +MidiPort::require_resolve () +{ + _resolve_required = true; +} + void MidiPort::transport_stopped () { @@ -210,6 +241,7 @@ MidiPort::reset () { Port::reset (); delete _buffer; + cerr << name() << " new MIDI buffer of size " << AudioEngine::instance()->raw_buffer_size (DataType::MIDI) << endl; _buffer = new MidiBuffer (AudioEngine::instance()->raw_buffer_size (DataType::MIDI)); } @@ -218,3 +250,9 @@ MidiPort::set_input_active (bool yn) { _input_active = yn; } + +void +MidiPort::set_always_parse (bool yn) +{ + _always_parse = yn; +}