X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fmidi_port.cc;h=880c1b5474b1e3e0b9d7284e681c628f971ec3e2;hb=bb9cc45cd22af67ac275a5e73accbe14fee664d8;hp=8fbccf17f7a39d65103fe79a6b92c3c3657cc8d0;hpb=959a7909c1adca430a63f783fd16687242a7be3d;p=ardour.git diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc index 8fbccf17f7..880c1b5474 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 @@ -17,98 +17,122 @@ */ #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) { - DataType dt(_type); - assert(dt == DataType::MIDI); - - reset(); - - + _buffer = new MidiBuffer (raw_buffer_size(0)); } - MidiPort::~MidiPort() { + delete _buffer; } void -MidiPort::cycle_start (jack_nframes_t nframes) +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 ()) { - const jack_nframes_t event_count - = jack_midi_get_event_count(jack_buffer); + 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()); + assert (event_count < _buffer->capacity()); - MidiEvent ev; + /* suck all relevant MIDI events from the JACK MIDI port buffer + into our MidiBuffer + */ - // FIXME: too slow, event struct is copied twice (here and MidiBuffer::push_back) - for (jack_nframes_t i=0; i < event_count; ++i) { + nframes_t off = offset + _port_offset; - // This will fail to compile if we change MidiEvent to our own class - jack_midi_event_get(static_cast(&ev), jack_buffer, i); + for (nframes_t i = 0; i < event_count; ++i) { - _buffer.push_back(ev); - // Convert note ons with velocity 0 to proper note offs - // FIXME: Jack MIDI should guarantee this - does it? - //if (ev->buffer[0] == MIDI_CMD_NOTE_ON && ev->buffer[2] == 0) - // ev->buffer[0] = MIDI_CMD_NOTE_OFF; + jack_midi_event_t ev; + + jack_midi_event_get (&ev, jack_buffer, i); + + if (ev.time > off && ev.time < off+nframes) { + _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; +} + +void +MidiPort::cycle_split () +{ + _has_been_mixed_down = false; +} + +void +MidiPort::flush_buffers (nframes_t nframes, nframes_t offset) +{ + if (sends_output ()) { - // We're an output - copy events from internal buffer to Jack buffer - - void* jack_buffer = jack_port_get_buffer(_port, _nframes_this_cycle); + void* jack_buffer = jack_port_get_buffer (_jack_port, nframes); - const jack_nframes_t event_count = _buffer.size(); - - //if (event_count > 0) - // cerr << "MIDIPort writing " << event_count << " events." << endl; + for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) { + const Evoral::Event& ev = *i; - jack_midi_clear_buffer(jack_buffer); - for (jack_nframes_t i=0; i < event_count; ++i) { - const jack_midi_event_t& ev = _buffer[i]; - assert(ev.time < _nframes_this_cycle); - jack_midi_event_write(jack_buffer, ev.time, ev.buffer, ev.size); + // 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) { + jack_midi_event_write (jack_buffer, (jack_nframes_t) ev.time(), ev.buffer(), ev.size()); + } + } } - - _nframes_this_cycle = 0; } + +size_t +MidiPort::raw_buffer_size (nframes_t nframes) const +{ + return jack_midi_max_event_size(jack_port_get_buffer(_jack_port, nframes)); +} +