X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fmidi_port.cc;h=6858fd1cbd0e9941a32d768ccf86b180a5c3e399;hb=7ab8dbc2fe679d75821ca585dd7c2663f640116e;hp=ba8d1aa841b87cc43088ee23f9cee3d1ce7359a7;hpb=7ff7f4013dfbbf18d08e397230ad2486fa7ff58f;p=ardour.git diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc index ba8d1aa841..6858fd1cbd 100644 --- a/libs/ardour/midi_port.cc +++ b/libs/ardour/midi_port.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2006 Paul Davis + Copyright (C) 2006 Paul Davis 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 @@ -19,93 +19,151 @@ #include #include -#include -#include +#include "ardour/midi_port.h" +#include "ardour/data_type.h" using namespace ARDOUR; using namespace std; -MidiPort::MidiPort(jack_port_t* p) - : Port(p) - , _buffer(4096) // FIXME FIXME FIXME Jack needs to tell us this - , _nframes_this_cycle(0) +MidiPort::MidiPort (const std::string& name, Flags flags) + : Port (name, DataType::MIDI, flags) + , _has_been_mixed_down (false) + , _resolve_in_process (false) { - DataType dt(_type); - assert(dt == DataType::MIDI); - - reset(); - - + _buffer = new MidiBuffer (raw_buffer_size(0)); } - MidiPort::~MidiPort() { + delete _buffer; } void MidiPort::cycle_start (nframes_t nframes) { - _buffer.clear(); - assert(_buffer.size() == 0); + _buffer->clear (); + assert (_buffer->size () == 0); - _nframes_this_cycle = nframes; + if (sends_output ()) { + jack_midi_clear_buffer (jack_port_get_buffer (_jack_port, nframes)); + } +} - if (_flags & JackPortIsOutput) { - _buffer.silence(nframes); - assert(_buffer.size() == 0); - return; +MidiBuffer & +MidiPort::get_midi_buffer (nframes_t nframes, nframes_t offset) +{ + if (_has_been_mixed_down) { + return *_buffer; } - // We're an input - copy Jack events to internal buffer - - void* jack_buffer = jack_port_get_buffer(_port, nframes); + if (receives_input ()) { + + void* jack_buffer = jack_port_get_buffer (_jack_port, nframes); + const nframes_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 + into our MidiBuffer + */ - const nframes_t event_count - = jack_midi_get_event_count(jack_buffer); + nframes_t off = offset + _port_offset; - assert(event_count < _buffer.capacity()); + for (nframes_t i = 0; i < event_count; ++i) { - jack_midi_event_t ev; + jack_midi_event_t ev; - for (nframes_t i=0; i < event_count; ++i) { + jack_midi_event_get (&ev, jack_buffer, i); - jack_midi_event_get(&ev, jack_buffer, i); +#if 0 + if (ev.buffer[0] == 0xfe) { + /* throw away active sensing */ + continue; + } +#endif + if (ev.time > off && ev.time < off+nframes) { + _buffer->push_back (ev); + } + } - _buffer.push_back(ev); + if (nframes) { + _has_been_mixed_down = true; + } + + } else { + _buffer->silence (nframes); } - assert(_buffer.size() == event_count); + if (nframes) { + _has_been_mixed_down = true; + } - //if (_buffer.size() > 0) - // cerr << "MIDIPort got " << event_count << " events." << endl; + return *_buffer; } + void -MidiPort::cycle_end() +MidiPort::cycle_end (nframes_t /*nframes*/) { - if (_flags & JackPortIsInput) { - _nframes_this_cycle = 0; - return; - } + _has_been_mixed_down = false; +} - // We're an output - copy events from internal buffer to Jack buffer - - void* jack_buffer = jack_port_get_buffer(_port, _nframes_this_cycle); - - const nframes_t event_count = _buffer.size(); - - //if (event_count > 0) - // cerr << "MIDIPort writing " << event_count << " events." << endl; - - jack_midi_clear_buffer(jack_buffer); - for (nframes_t i=0; i < event_count; ++i) { - const MidiEvent& ev = _buffer[i]; - // event times should be frames, relative to cycle start - assert(ev.time >= 0); - assert(ev.time < _nframes_this_cycle); - jack_midi_event_write(jack_buffer, (jack_nframes_t)ev.time, ev.buffer, ev.size); +void +MidiPort::cycle_split () +{ + _has_been_mixed_down = false; +} + +void +MidiPort::flush_buffers (nframes_t nframes, nframes64_t time, nframes_t offset) +{ + if (sends_output ()) { + + void* jack_buffer = jack_port_get_buffer (_jack_port, nframes); + + // Feed the data through the MidiStateTracker + bool did_loop; + + _midi_state_tracker.track (_buffer->begin(), _buffer->end(), did_loop); + + if (did_loop || _resolve_in_process) { + /* add necessary note offs */ + _midi_state_tracker.resolve_notes (*_buffer, time); + } + + _resolve_in_process = false; + + for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) { + const Evoral::Event& ev = *i; + + // event times are in frames, relative to cycle start + + // XXX split cycle start or cycle start? + + assert(ev.time() < (nframes+offset+_port_offset)); + + if (ev.time() >= offset + _port_offset) { + if (jack_midi_event_write (jack_buffer, (jack_nframes_t) ev.time(), ev.buffer(), ev.size()) != 0) { + cerr << "write failed, drop flushed note off on the floor, time " << ev.time() << " > " << offset << " + " << _port_offset + << endl; + } + } else { + cerr << "drop flushed note off on the floor, time " << ev.time() << " > " << offset << " + " << _port_offset + << endl; + } + } } - - _nframes_this_cycle = 0; } + +void +MidiPort::transport_stopped () +{ + _resolve_in_process = true; +} + +size_t +MidiPort::raw_buffer_size (nframes_t nframes) const +{ + return jack_midi_max_event_size(jack_port_get_buffer(_jack_port, nframes)); +} +