Merge branch 'master' into cairocanvas
[ardour.git] / libs / ardour / midi_port.cc
index 5589c6e501aea0f7ead75d7c37a90c1fdb95beaf..55280eb9428e82aed7fc611a53d866991f0b0b82 100644 (file)
@@ -33,6 +33,7 @@ MidiPort::MidiPort (const std::string& name, PortFlags 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));
 }
@@ -45,6 +46,8 @@ 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 ();
@@ -52,6 +55,24 @@ MidiPort::cycle_start (pframes_t nframes)
        if (sends_output ()) {
                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]);
+                       }
+               }
+       }
 }
 
 MidiBuffer &
@@ -67,11 +88,11 @@ MidiPort::get_midi_buffer (pframes_t nframes)
 
                        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) {
                                
                                pframes_t timestamp;
@@ -137,13 +158,13 @@ MidiPort::resolve_notes (void* port_buffer, MidiBuffer::TimeType when)
                 */
 
                if (port_engine.midi_event_put (port_buffer, when, ev, 3) != 0) {
-                       cerr << "failed to deliver sustain-zero on channel " << channel << " on port " << name() << endl;
+                       cerr << "failed to deliver sustain-zero on channel " << (int)channel << " on port " << name() << endl;
                }
 
                ev[1] = MIDI_CTL_ALL_NOTES_OFF;
 
                if (port_engine.midi_event_put (port_buffer, 0, ev, 3) != 0) {
-                       cerr << "failed to deliver ALL NOTES OFF on channel " << channel << " on port " << name() << endl;
+                       cerr << "failed to deliver ALL NOTES OFF on channel " << (int)channel << " on port " << name() << endl;
                }
        }
 }
@@ -153,12 +174,21 @@ MidiPort::flush_buffers (pframes_t nframes)
 {
        if (sends_output ()) {
 
-               void* port_buffer = port_engine.get_buffer (_port_handle, 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 (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,11 +205,16 @@ MidiPort::flush_buffers (pframes_t nframes)
                                             << ev.time() << " > " << _global_port_buffer_offset + _port_buffer_offset << endl;
                                }
                        } else {
-                               cerr << "drop flushed event on the floor, time " << ev
+                               cerr << "drop flushed event on the floor, time " << ev.time()
                                     << " 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 ();
        }
 }
 
@@ -215,3 +250,9 @@ MidiPort::set_input_active (bool yn)
 {
        _input_active = yn;
 }
+
+void
+MidiPort::set_always_parse (bool yn)
+{
+       _always_parse = yn;
+}