2 Copyright (C) 2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "ardour/midi_port.h"
23 #include "ardour/data_type.h"
25 using namespace ARDOUR
;
28 MidiPort::MidiPort (const std::string
& name
, Flags flags
)
29 : Port (name
, DataType::MIDI
, flags
)
30 , _has_been_mixed_down (false)
31 , _resolve_in_process (false)
33 _buffer
= new MidiBuffer (raw_buffer_size(0));
42 MidiPort::cycle_start (pframes_t nframes
)
44 Port::cycle_start (nframes
);
48 assert (_buffer
->size () == 0);
50 if (sends_output ()) {
51 jack_midi_clear_buffer (jack_port_get_buffer (_jack_port
, nframes
));
56 MidiPort::get_midi_buffer (pframes_t nframes
)
58 if (_has_been_mixed_down
) {
62 if (receives_input ()) {
64 void* jack_buffer
= jack_port_get_buffer (_jack_port
, nframes
);
65 const pframes_t event_count
= jack_midi_get_event_count (jack_buffer
);
67 assert (event_count
< _buffer
->capacity());
69 /* suck all relevant MIDI events from the JACK MIDI port buffer
73 for (pframes_t i
= 0; i
< event_count
; ++i
) {
77 jack_midi_event_get (&ev
, jack_buffer
, i
);
79 if (ev
.buffer
[0] == 0xfe) {
80 /* throw away active sensing */
84 /* check that the event is in the acceptable time range */
86 if ((ev
.time
>= (_global_port_buffer_offset
+ _port_buffer_offset
)) &&
87 (ev
.time
< (_global_port_buffer_offset
+ _port_buffer_offset
+ nframes
))) {
88 _buffer
->push_back (ev
);
90 cerr
<< "Dropping incoming MIDI at time " << ev
.time
<< "; offset="
91 << _global_port_buffer_offset
<< " limit="
92 << (_global_port_buffer_offset
+ _port_buffer_offset
+ nframes
) << "\n";
97 _buffer
->silence (nframes
);
101 _has_been_mixed_down
= true;
109 MidiPort::cycle_end (pframes_t
/*nframes*/)
111 _has_been_mixed_down
= false;
115 MidiPort::cycle_split ()
117 _has_been_mixed_down
= false;
121 MidiPort::flush_buffers (pframes_t nframes
, framepos_t time
)
123 if (sends_output ()) {
125 void* jack_buffer
= jack_port_get_buffer (_jack_port
, nframes
);
127 // Feed the data through the MidiStateTracker
130 _midi_state_tracker
.track (_buffer
->begin(), _buffer
->end(), did_loop
);
132 if (did_loop
|| _resolve_in_process
) {
133 /* add necessary note offs */
134 _midi_state_tracker
.resolve_notes (*_buffer
, time
);
137 _resolve_in_process
= false;
139 for (MidiBuffer::iterator i
= _buffer
->begin(); i
!= _buffer
->end(); ++i
) {
140 const Evoral::Event
<framepos_t
>& ev
= *i
;
142 // event times are in frames, relative to cycle start
144 assert (ev
.time() < (nframes
+ _global_port_buffer_offset
+ _port_buffer_offset
));
146 if (ev
.time() >= _global_port_buffer_offset
+ _port_buffer_offset
) {
147 if (jack_midi_event_write (jack_buffer
, (jack_nframes_t
) ev
.time(), ev
.buffer(), ev
.size()) != 0) {
148 cerr
<< "write failed, drop flushed note off on the floor, time "
149 << ev
.time() << " > " << _global_port_buffer_offset
+ _port_buffer_offset
<< endl
;
152 cerr
<< "drop flushed event on the floor, time " << ev
.time()
153 << " < " << _global_port_buffer_offset
+ _port_buffer_offset
<< endl
;
160 MidiPort::transport_stopped ()
162 _resolve_in_process
= true;
166 MidiPort::raw_buffer_size (pframes_t nframes
) const
168 return jack_midi_max_event_size (jack_port_get_buffer (_jack_port
, nframes
));