torben's port buffer reworking; torben's panner automation loading patch (allows...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 8 Oct 2008 20:14:22 +0000 (20:14 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 8 Oct 2008 20:14:22 +0000 (20:14 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@3890 d708f5d6-7413-0410-9779-e7cbd77b26cf

26 files changed:
libs/ardour/ardour/audio_port.h
libs/ardour/ardour/base_audio_port.h
libs/ardour/ardour/base_midi_port.h
libs/ardour/ardour/io.h
libs/ardour/ardour/jack_audio_port.h
libs/ardour/ardour/jack_midi_port.h
libs/ardour/ardour/midi_buffer.h
libs/ardour/ardour/midi_port.h
libs/ardour/ardour/port.h
libs/ardour/audio_diskstream.cc
libs/ardour/audio_port.cc
libs/ardour/audio_track.cc
libs/ardour/audioengine.cc
libs/ardour/base_audio_port.cc
libs/ardour/base_midi_port.cc
libs/ardour/buffer_set.cc
libs/ardour/export_channel_configuration.cc
libs/ardour/io.cc
libs/ardour/jack_audio_port.cc
libs/ardour/jack_midi_port.cc
libs/ardour/midi_buffer.cc
libs/ardour/midi_diskstream.cc
libs/ardour/midi_port.cc
libs/ardour/midi_track.cc
libs/ardour/panner.cc
libs/ardour/session_process.cc

index 874f842d835e9a346080468b7df58a3387d581bb..fa416864e951535940ee264eca90a1043da3fd70 100644 (file)
@@ -35,10 +35,14 @@ class AudioPort : public BaseAudioPort, public PortFacade {
        void cycle_start (nframes_t nframes, nframes_t offset);
        void cycle_end (nframes_t nframes, nframes_t offset);
        
+       AudioBuffer& get_audio_buffer( nframes_t nframes, nframes_t offset );
+
   protected:
        friend class AudioEngine;
 
        AudioPort (const std::string&, Flags, bool external, nframes_t); 
+  private:
+       bool _has_been_mixed_down;
 };
  
 } // namespace ARDOUR
index 791928fa03de0717732c55ef7a1137554efe3e4a..5bad90150b6bdb253501a9c6778da4d37a8f6023 100644 (file)
@@ -41,15 +41,11 @@ class BaseAudioPort : public virtual Port {
 
        DataType type() const { return DataType::AUDIO; }
 
-       virtual Buffer& get_buffer () {
-               assert (_buffer);
-               return *_buffer;
+       virtual Buffer& get_buffer ( nframes_t nframes, nframes_t offset ) {
+               return get_audio_buffer( nframes, offset);
        }
 
-       virtual AudioBuffer& get_audio_buffer() {
-               assert (_buffer);
-               return *_buffer;
-       }
+       virtual AudioBuffer& get_audio_buffer (nframes_t nframes, nframes_t offset) = 0;
        
        void reset ();
 
index 1c9a69d48d0c31e2608fbb28de3c85549f3c0b73..5ea18fce43b01ac478ee7df29ddd287ad53e0e87 100644 (file)
@@ -37,15 +37,11 @@ class BaseMidiPort : public virtual Port {
        
        DataType type() const { return DataType::MIDI; }
 
-       Buffer& get_buffer() {
-               assert (_buffer);
-               return *_buffer;
+       Buffer& get_buffer( nframes_t nframes, nframes_t offset ) {
+               return get_midi_buffer( nframes, offset );
        }
 
-       MidiBuffer& get_midi_buffer() {
-               assert (_buffer);
-               return *_buffer;
-       }
+       virtual MidiBuffer& get_midi_buffer (nframes_t nframes, nframes_t offset ) = 0;
        
        size_t capacity() { return _buffer->capacity(); }
        size_t size()     { return _buffer->size(); }
index af26319e828c0ef7bfdc6f765240aafabfb849c0..69473b57479f406c2467ea2b2869ff028ade8c49 100644 (file)
@@ -289,6 +289,7 @@ class IO : public SessionObject, public AutomatableControls, public Latent
        bool                _public_ports;
 
        virtual void prepare_inputs (nframes_t nframes, nframes_t offset);
+       virtual void flush_outputs (nframes_t nframes, nframes_t offset);
 
        virtual void set_deferred_state() {}
 
index 703fb81fa3cc8afaeee649fc561241557cb89106..5ca27132e0b571f930ab3e500dd49f291a873321 100644 (file)
@@ -32,18 +32,21 @@ namespace ARDOUR {
 class AudioEngine;
 class JackAudioPort : public JackPort, public BaseAudioPort {
    public:
-       void cycle_start (nframes_t nframes, nframes_t offset) {
-               _buffer->set_data ((Sample*) jack_port_get_buffer (_port, nframes) + offset, nframes);
-       }
+       void cycle_end (nframes_t nframes, nframes_t offset);
+       void cycle_start (nframes_t nframes, nframes_t offset);
 
        int reestablish ();
 
+       AudioBuffer& get_audio_buffer( nframes_t nframes, nframes_t offset );
+
   protected:
        friend class AudioPort;
 
        JackAudioPort (const std::string& name, Flags flags, AudioBuffer* buf);
 
        AudioBuffer* _source_buffer;
+  private:
+       bool    _has_been_mixed_down;
 };
  
 } // namespace ARDOUR
index d1fb5cc4fb4ea3622b0613146b5e121da290bb7a..91cbd400aa230e7334a913326243f761acf8ff8b 100644 (file)
@@ -39,12 +39,17 @@ class JackMidiPort : public JackPort, public BaseMidiPort {
    public:
        void cycle_start (nframes_t nframes, nframes_t offset);
        void cycle_end (nframes_t nframes, nframes_t offset);
+       void flush_buffers (nframes_t nframes, nframes_t offset);
        void set_buffer (MidiBuffer& buf);
 
+       MidiBuffer& get_midi_buffer( nframes_t nframes, nframes_t offset );
+
   protected:
        friend class MidiPort;
 
        JackMidiPort (const std::string&, Flags, MidiBuffer*);
+  private:
+       bool _has_been_mixed_down;
 };
  
 } // namespace ARDOUR
index 606cbd0ec80db06956af2eb7dcff8b95231a577c..812f697aa3de32f1765063c12bf47ba2bb09e3e4 100644 (file)
@@ -46,6 +46,7 @@ public:
        void resize(size_t);
 
        bool merge(const MidiBuffer& a, const MidiBuffer& b);
+       bool merge_in_place( const MidiBuffer &other );
        
        struct iterator {
                iterator(MidiBuffer& b, size_t i) : buffer(b), index(i) {}
index 485834aaffb0d7d7dc0c6ab47af88e72e1174e41..a5a269b1ef62b8c0d89e69731be8c560f9ac55a8 100644 (file)
@@ -35,11 +35,16 @@ class MidiPort : public BaseMidiPort, public PortFacade {
 
        void cycle_start (nframes_t nframes, nframes_t offset);
        void cycle_end (nframes_t nframes, nframes_t offset);
+       void flush_buffers (nframes_t nframes, nframes_t offset);
+
+       MidiBuffer& get_midi_buffer( nframes_t nframes, nframes_t offset );
 
   protected:
        friend class AudioEngine;
 
        MidiPort (const std::string& name, Flags, bool external, nframes_t bufsize);
+  private:
+       bool _has_been_mixed_down;
 };
  
 } // namespace ARDOUR
index 084022541d3993d3c9639237215e87f0dbc501a8..ad81d6763fbc656b2af0024cb8bbe82588407c1f 100644 (file)
@@ -79,8 +79,9 @@ class Port : public virtual sigc::trackable {
 
        virtual void cycle_start (nframes_t nframes, nframes_t offset) {}
        virtual void cycle_end (nframes_t nframes, nframes_t offset) {}
+       virtual void flush_buffers (nframes_t nframes, nframes_t offset ) {}
        virtual DataType type() const = 0;
-       virtual Buffer& get_buffer() = 0;
+       virtual Buffer& get_buffer( nframes_t nframes, nframes_t offset ) = 0;
 
        virtual bool connected () const;
        virtual bool connected_to (const std::string& portname) const;
index e9f4b9ea15243cf66c92f4ea9d098b3899b31b85..4cf834b5c14deb86198373ef1d0ad2298aeb1557 100644 (file)
@@ -655,8 +655,8 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
 
                                AudioPort* const ap = _io->audio_input(n);
                                assert(ap);
-                               assert(rec_nframes <= ap->get_audio_buffer().capacity());
-                               memcpy (chaninfo->current_capture_buffer, ap->get_audio_buffer().data(rec_nframes, offset + rec_offset), sizeof (Sample) * rec_nframes);
+                               assert(rec_nframes <= ap->get_audio_buffer( nframes, offset ).capacity());
+                               memcpy (chaninfo->current_capture_buffer, ap->get_audio_buffer( nframes, offset ).data(rec_nframes, offset + rec_offset), sizeof (Sample) * rec_nframes);
 
                        } else {
 
@@ -670,7 +670,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
                                AudioPort* const ap = _io->audio_input(n);
                                assert(ap);
 
-                               Sample* buf = ap->get_audio_buffer().data(nframes, offset);
+                               Sample* buf = ap->get_audio_buffer( nframes, offset ).data(nframes, offset);
                                nframes_t first = chaninfo->capture_vector.len[0];
 
                                memcpy (chaninfo->capture_wrap_buffer, buf, sizeof (Sample) * first);
index 714be28f3409c4c0ce7fe4006fd7621bdb9598ba..0e37313d018a175f42a5c37c13d7f870a35617a5 100644 (file)
@@ -29,6 +29,7 @@ AudioPort::AudioPort (const std::string& name, Flags flags, bool external, nfram
        : Port (name, flags)
        , BaseAudioPort (name, flags)
        , PortFacade (name, flags)
+       , _has_been_mixed_down( false )
 {
        if (!external || receives_input()) {
 
@@ -55,9 +56,9 @@ AudioPort::AudioPort (const std::string& name, Flags flags, bool external, nfram
 
                _ext_port = new JackAudioPort (name, flags, 0);
 
-               if (sends_output()) {
-                       _buffer = &dynamic_cast<JackAudioPort*>(_ext_port)->get_audio_buffer();
-               } 
+               //if (sends_output()) {
+               //      _buffer = &dynamic_cast<JackAudioPort*>(_ext_port)->get_audio_buffer( nframes, offset );
+               //
 
                Port::set_name (_ext_port->name());
        }
@@ -92,11 +93,19 @@ AudioPort::cycle_start (nframes_t nframes, nframes_t offset)
        if (_ext_port) {
                _ext_port->cycle_start (nframes, offset);
        }
+       _has_been_mixed_down = false;
+}
+
+AudioBuffer &
+AudioPort::get_audio_buffer( nframes_t nframes, nframes_t offset ) {
+
+       if (_has_been_mixed_down)       
+               return *_buffer;
 
        if (_flags & IsInput) {
 
                if (_ext_port) {
-                       _buffer->read_from (dynamic_cast<BaseAudioPort*>(_ext_port)->get_audio_buffer(), nframes, offset);
+                       _buffer->read_from (dynamic_cast<BaseAudioPort*>(_ext_port)->get_audio_buffer (nframes, offset), nframes, offset);
 
                        if (!_connections.empty()) {
                                (*_mixdown) (_connections, _buffer, nframes, offset, false);
@@ -115,12 +124,20 @@ AudioPort::cycle_start (nframes_t nframes, nframes_t offset)
                
                // XXX if we could get the output stage to not purely mix into, but also
                // to initially overwrite the buffer, we could avoid this silence step.
-               
-               _buffer->silence (nframes, offset);
+               if (_ext_port) {
+                       _buffer = & (dynamic_cast<BaseAudioPort*>(_ext_port)->get_audio_buffer( nframes, offset ));
+               }
+               if (nframes)
+                       _buffer->silence (nframes, offset);
        }
+       if (nframes)
+               _has_been_mixed_down = true;
+
+       return *_buffer;
 }
 
 void
 AudioPort::cycle_end (nframes_t nframes, nframes_t offset)
 {
+       _has_been_mixed_down=false;
 }
index 0418074ef20eab4163d87c3cd2b9a780db9c2dd0..d30899caf8605b44490007c82662f1db3002ab9f 100644 (file)
@@ -540,6 +540,8 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
 
        transport_frame = _session.transport_frame();
 
+       prepare_inputs( nframes, offset );
+
        if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
                /* need to do this so that the diskstream sets its
                   playback distance to zero, thus causing diskstream::commit
index 3122ff760c71eb22d8378dd213310b039cebe881..0ae71f739c6f789a598d647622ab14828c13b8ba 100644 (file)
@@ -351,9 +351,7 @@ AudioEngine::process_callback (nframes_t nframes)
                   which requires interleaving with route processing.
                */
 
-               if ((*i)->sends_output()) {
-                       (*i)->cycle_start (nframes, 0);
-               }
+               (*i)->cycle_start (nframes, 0);
        }
 
        if (_freewheeling) {
@@ -368,12 +366,6 @@ AudioEngine::process_callback (nframes_t nframes)
                }
        }
        
-       // Finalize ports (ie write data if necessary)
-
-       for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
-               (*i)->cycle_end (nframes, 0);
-       }
-
        if (_freewheeling) {
                return 0;
        }
@@ -412,11 +404,18 @@ AudioEngine::process_callback (nframes_t nframes)
                        Port *port = (*i);
                        
                        if (port->sends_output()) {
-                               port->get_buffer().silence(nframes);
+                               port->get_buffer(nframes, 0 ).silence(nframes);
                        }
                }
        }
 
+       // Finalize ports (ie write data if necessary)
+
+       for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
+
+               (*i)->cycle_end (nframes, 0);
+       }
+
        _processed_frames = next_processed_frames;
        return 0;
 }
@@ -523,9 +522,7 @@ AudioEngine::set_session (Session *s)
                boost::shared_ptr<Ports> p = ports.reader();
 
                for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
-                       if ((*i)->sends_output()) {
-                               (*i)->cycle_start (blocksize, 0);
-                       }
+                       (*i)->cycle_start (blocksize, 0);
                }
 
                s->process (blocksize);
index ceec4c1d3a1c0ad6d7e0b282b807b0c254702e43..0675a4c99288f5b2410c8a64be1897f423e03eb2 100644 (file)
@@ -64,12 +64,12 @@ BaseAudioPort::default_mixdown (const set<Port*>& ports, AudioBuffer* dest, nfra
        set<Port*>::const_iterator p = ports.begin();
 
        if (first_overwrite) {
-               dest->read_from ((dynamic_cast<BaseAudioPort*>(*p))->get_audio_buffer(), cnt, offset);
+               dest->read_from ((dynamic_cast<BaseAudioPort*>(*p))->get_audio_buffer( cnt, offset ), cnt, offset);
                p++;
        }
 
        for (; p != ports.end(); ++p) {
-               dest->accumulate_from ((dynamic_cast<BaseAudioPort*>(*p))->get_audio_buffer(), cnt, offset);
+               dest->accumulate_from ((dynamic_cast<BaseAudioPort*>(*p))->get_audio_buffer( cnt, offset ), cnt, offset);
        }
 }
 
index 49d748dd20bcb6871c5d783519c8dab1521a9297..d679c7c04f7e66fc6845ea02aff9100e967c172a 100644 (file)
@@ -48,15 +48,15 @@ BaseMidiPort::default_mixdown (const set<Port*>& ports, MidiBuffer* dest, nframe
 
        if (first_overwrite) {
                cout << "first overwrite" << endl;
-               dest->read_from ((dynamic_cast<BaseMidiPort*>(*p))->get_midi_buffer(), cnt, offset);
+               dest->read_from ((dynamic_cast<BaseMidiPort*>(*p))->get_midi_buffer(cnt, offset), cnt, offset);
                p++;
        }
 
        // XXX DAVE: this is just a guess
 
        for (; p != ports.end(); ++p) {
-               cout << "merge" << endl;
-               dest->merge (*dest, (dynamic_cast<BaseMidiPort*>(*p))->get_midi_buffer());
+               //cout << "merge" << endl;
+               dest->merge (*dest, (dynamic_cast<BaseMidiPort*>(*p))->get_midi_buffer(cnt, offset));
        }
 }
 
index 65e9f8ac8f0695e9bc012f9479e1188c76f777be..5b6f0711503dd2891b2c96460f5983b0ab50f639 100644 (file)
@@ -71,7 +71,7 @@ BufferSet::attach_buffers(PortSet& ports)
 
                for (PortSet::iterator p = ports.begin(*t); p != ports.end(*t); ++p) {
                        assert(p->type() == *t);
-                       v.push_back(&(p->get_buffer()));
+                       v.push_back(&(p->get_buffer(0,0)));
                }
 
        }
index e6eb84be0651a31e12a44eff2fd70dd8040a0229..a092af88c1d57a78f49892a9c3920aea209ab92d 100644 (file)
@@ -46,7 +46,7 @@ ExportChannel::read_ports (float * data, nframes_t frames) const
 
        for (iterator it = begin(); it != end(); ++it) {
                if (*it != 0) {
-                       Sample* port_buffer = (*it)->get_audio_buffer().data();
+                       Sample* port_buffer = (*it)->get_audio_buffer( frames, 0).data();
                        
                        for (uint32_t i = 0; i < frames; ++i) {
                                data[i] += (float) port_buffer[i];
index b994b173589ffe78101a90b1aef4b1d96b5be5f4..e245712feee8acb441b4554be4173b39988adaff 100644 (file)
@@ -231,7 +231,7 @@ IO::silence (nframes_t nframes, nframes_t offset)
        /* io_lock, not taken: function must be called from Session::process() calltree */
 
        for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
-               i->get_buffer().silence (nframes, offset);
+               i->get_buffer(nframes,offset).silence (nframes, offset);
        }
 }
 
@@ -323,8 +323,7 @@ IO::collect_input (BufferSet& outs, nframes_t nframes, nframes_t offset)
                
                BufferSet::iterator o = outs.begin(*t);
                for (PortSet::iterator i = _inputs.begin(*t); i != _inputs.end(*t); ++i, ++o) {
-                       (*i).cycle_start (nframes, offset);
-                       o->read_from(i->get_buffer(), nframes, offset);
+                       o->read_from(i->get_buffer(nframes,offset), nframes, offset);
                }
 
        }
@@ -2766,8 +2765,20 @@ void
 IO::prepare_inputs (nframes_t nframes, nframes_t offset)
 {
        /* io_lock, not taken: function must be called from Session::process() calltree */
+}
 
-       for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
-               (*i).cycle_start (nframes, offset);
+void
+IO::flush_outputs (nframes_t nframes, nframes_t offset)
+{
+       /* io_lock, not taken: function must be called from Session::process() calltree */
+       for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
+
+               /* Only run cycle_start() on output ports, because 
+                  inputs must be done in the correct processing order,
+                  which requires interleaving with route processing.
+               */
+
+               (*i).flush_buffers (nframes, offset);
        }
+               
 }
index 7ce00b8f11da24b96223418ac719c9d0fa253153..ed52eada9ca6a95ed188df769478670e7fbb96c2 100644 (file)
@@ -26,6 +26,7 @@ JackAudioPort::JackAudioPort (const std::string& name, Flags flgs, AudioBuffer*
        : Port (name, flgs)
        , JackPort (name, DataType::AUDIO, flgs)
        , BaseAudioPort (name, flgs)
+       , _has_been_mixed_down( false )
 {
        if (buf) {
 
@@ -53,3 +54,29 @@ JackAudioPort::reestablish ()
        return ret;
 }
 
+AudioBuffer&
+JackAudioPort::get_audio_buffer (nframes_t nframes, nframes_t offset) {
+       assert (_buffer);
+
+       if (_has_been_mixed_down)
+               return *_buffer;
+
+       if( _flags & IsInput )
+               _buffer->set_data ((Sample*) jack_port_get_buffer (_port, nframes), nframes+offset);
+
+
+       if (nframes)
+               _has_been_mixed_down = true;
+
+       return *_buffer;
+}
+
+void
+JackAudioPort::cycle_start (nframes_t nframes, nframes_t offset) {
+       if( _flags & IsOutput )
+               _buffer->set_data ((Sample*) jack_port_get_buffer (_port, nframes), nframes+offset);
+}
+void
+JackAudioPort::cycle_end (nframes_t nframes, nframes_t offset) {
+       _has_been_mixed_down=false;
+}
index d831864ec962e432eb15384bf572716b9d97029f..3c3f50c9bb4cba043ae3a223798d121404c5c061 100644 (file)
@@ -24,6 +24,7 @@ JackMidiPort::JackMidiPort (const std::string& name, Flags flgs, MidiBuffer* buf
        : Port (name, flgs)
        , JackPort (name, DataType::MIDI, flgs)
        , BaseMidiPort (name, flgs) 
+       , _has_been_mixed_down (false)
 {
        // MIDI ports always need a buffer since jack buffer format is different
        assert(buf);
@@ -40,10 +41,27 @@ JackMidiPort::cycle_start (nframes_t nframes, nframes_t offset)
        _buffer->clear();
        assert(_buffer->size() == 0);
 
-       if (_flags & IsOutput) {
+       if (_flags & IsInput) {
                return;
        }
 
+       // We're an output - delete the midi_events.
+       
+       void* jack_buffer = jack_port_get_buffer (_port, nframes);
+
+       jack_midi_clear_buffer (jack_buffer);
+}
+
+MidiBuffer &
+JackMidiPort::get_midi_buffer( nframes_t nframes, nframes_t offset ) {
+
+       if (_has_been_mixed_down)
+           return *_buffer;
+
+       if (_flags & IsOutput) {
+               return *_buffer;
+       }
+
        // We're an input - copy Jack events to internal buffer
        
        void* jack_buffer = jack_port_get_buffer(_port, nframes);
@@ -57,13 +75,19 @@ JackMidiPort::cycle_start (nframes_t nframes, nframes_t offset)
 
                jack_midi_event_get (&ev, jack_buffer, i);
 
-               _buffer->push_back (ev);
+               // i guess this should do but i leave it off to test the rest first.
+               //if (ev.time > offset && ev.time < offset+nframes)
+                       _buffer->push_back (ev);
        }
 
        assert(_buffer->size() == event_count);
 
        /*if (_buffer->size() > 0)
                cerr << "JackMIDIPort got " << event_count << " events (buf " << _buffer << ")" << endl;*/
+       if (nframes)
+               _has_been_mixed_down = true;
+
+       return *_buffer;
 }
 
 void
@@ -71,6 +95,9 @@ JackMidiPort::cycle_end (nframes_t nframes, nframes_t offset)
 {
        /* FIXME: offset */
 
+       _has_been_mixed_down = false;
+
+#if 0
        if (_flags & IsInput) {
                return;
        }
@@ -81,6 +108,27 @@ JackMidiPort::cycle_end (nframes_t nframes, nframes_t offset)
 
        jack_midi_clear_buffer (jack_buffer);
 
+       for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) {
+               const Evoral::Event& ev = *i;
+               // event times should be frames, relative to cycle start
+               assert(ev.time() >= 0);
+               assert(ev.time() < nframes);
+               jack_midi_event_write (jack_buffer, (jack_nframes_t) ev.time(), ev.buffer(), ev.size());
+       }
+#endif
+}
+
+void
+JackMidiPort::flush_buffers (nframes_t nframes, nframes_t offset)
+{
+       /* FIXME: offset */
+
+       if (_flags & IsInput) {
+               return;
+       }
+
+       void* jack_buffer = jack_port_get_buffer (_port, nframes);
+
        for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) {
                const Evoral::Event& ev = *i;
                // event times should be frames, relative to cycle start
index f1f6b9b633450e8b8e8b84fc37aaf8326923b266..6f0620cae1d9588cda987773c2d6eb789e583d8d 100644 (file)
@@ -229,6 +229,38 @@ MidiBuffer::silence(nframes_t dur, nframes_t offset)
        _silent = true;
 }
 
+bool
+MidiBuffer::merge_in_place( const MidiBuffer &other )
+{
+       if( other.size() == 0 )
+               return true;
+
+       if( this->size() == 0 ) {
+               copy( other );
+               return true;
+       }
+
+       {
+               MidiBuffer merge_buffer( 0 );
+               Evoral::MIDIEvent onstack_events[_capacity];
+               uint8_t   onstack_data[_capacity * MAX_EVENT_SIZE];
+               merge_buffer._events = onstack_events;
+               merge_buffer._data = onstack_data;
+               merge_buffer._size = 0;
+
+               bool retval = merge_buffer.merge( *this, other );
+
+               copy( merge_buffer );
+
+               // set pointers to zero again, so destructor
+               // does not end in calling free() for memory
+               // on the stack;
+               merge_buffer._events = 0;
+               merge_buffer._data = 0;
+
+               return retval;
+       }
+}
 
 /** Clear, and merge \a a and \a b into this buffer.
  *
@@ -241,14 +273,18 @@ MidiBuffer::merge(const MidiBuffer& a, const MidiBuffer& b)
 {
        _size = 0;
 
-       // Die if a merge isn't necessary as it's expensive
-       assert(a.size() > 0 && b.size() > 0);
+       // This is mostly the case :(
+       if( this == &a )
+           merge_in_place( b );
+
+       if( this == &b )
+           merge_in_place( a );
 
        size_t a_index = 0;
        size_t b_index = 0;
        size_t count = a.size() + b.size();
 
-       while (count > 0 && a_index < a.size() && b_index < b.size()) {
+       while (count > 0) {
                
                if (size() == capacity()) {
                        cerr << "WARNING: MIDI buffer overrun, events lost!" << endl;
@@ -256,11 +292,11 @@ MidiBuffer::merge(const MidiBuffer& a, const MidiBuffer& b)
                }
                
                if (a_index == a.size()) {
-                       push_back(a[a_index]);
-                       ++a_index;
-               } else if (b_index == b.size()) {
                        push_back(b[b_index]);
                        ++b_index;
+               } else if (b_index == b.size()) {
+                       push_back(a[a_index]);
+                       ++a_index;
                } else {
                        const Evoral::MIDIEvent& a_ev = a[a_index];
                        const Evoral::MIDIEvent& b_ev = b[b_index];
index bb7f2931f4ee020df198fe0b40ad60f2965b8003..0b79213a23c9e0e812009b2e60a22b26b3f24222 100644 (file)
@@ -514,10 +514,10 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t
 
                // Pump entire port buffer into the ring buffer (FIXME: split cycles?)
                //_capture_buf->write(_source_port->get_midi_buffer(), transport_frame);
-               size_t num_events = _source_port->get_midi_buffer().size();
+               size_t num_events = _source_port->get_midi_buffer( nframes, offset ).size();
                size_t to_write = std::min(_capture_buf->write_space(), num_events);
 
-               MidiBuffer::iterator port_iter = _source_port->get_midi_buffer().begin();
+               MidiBuffer::iterator port_iter = _source_port->get_midi_buffer( nframes, offset ).begin();
 
                for (size_t i=0; i < to_write; ++i) {
                        const Evoral::MIDIEvent& ev = *port_iter;
index 14f88f2ad5a0f59d95a52560432cf977290ecede..779d31724760b345867f9b833899014332bf0269 100644 (file)
@@ -30,6 +30,7 @@ MidiPort::MidiPort (const std::string& name, Flags flags, bool external, nframes
        : Port (name, flags)
        , BaseMidiPort (name, flags)
        , PortFacade (name, flags)
+       , _has_been_mixed_down (false)
 {
        // FIXME: size kludge (see BufferSet::ensure_buffers)
        // Jack needs to tell us this
@@ -73,14 +74,21 @@ MidiPort::cycle_start (nframes_t nframes, nframes_t offset)
        if (_ext_port) {
                _ext_port->cycle_start (nframes, offset);
        }
+}
+
+MidiBuffer &
+MidiPort::get_midi_buffer( nframes_t nframes, nframes_t offset ) {
        
+       if (_has_been_mixed_down)
+           return *_buffer;
+
        if (_flags & IsInput) {
                        
                if (_ext_port) {
                
                        BaseMidiPort* mprt = dynamic_cast<BaseMidiPort*>(_ext_port);
                        assert(mprt);
-                       assert(&mprt->get_midi_buffer() == _buffer);
+                       assert(&mprt->get_midi_buffer(nframes,offset) == _buffer);
 
                        if (!_connections.empty()) {
                                (*_mixdown) (_connections, _buffer, nframes, offset, false);
@@ -96,9 +104,12 @@ MidiPort::cycle_start (nframes_t nframes, nframes_t offset)
                }
 
        } else {
-                       
                _buffer->silence (nframes, offset);
        }
+       if (nframes)
+               _has_been_mixed_down = true;
+
+       return *_buffer;
 }
 
        
@@ -108,5 +119,13 @@ MidiPort::cycle_end (nframes_t nframes, nframes_t offset)
        if (_ext_port) {
                _ext_port->cycle_end (nframes, offset);
        }
+       _has_been_mixed_down = false;
 }
 
+void
+MidiPort::flush_buffers (nframes_t nframes, nframes_t offset)
+{
+       if (_ext_port) {
+               _ext_port->flush_buffers (nframes, offset);
+       }
+}
index d60aba8bbccc593d7eb692af8ef7e1770c6bbc82..662d19df3c1a3f8c2702096d53679007d5cdfa4d 100644 (file)
@@ -79,7 +79,7 @@ MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mo
 }
 
 MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
-       : Track (sess, node)
+       : Track (sess, node, DataType::MIDI )
        , _immediate_events(1024) // FIXME: size?
        , _note_mode(Sustained)
 {
@@ -438,6 +438,11 @@ MidiTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
        int dret;
        boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
        
+       // I guess this is the right place to call cycle_start for our ports.
+       // but it actually sucks, to directly mess with the IO.... oh well.
+       
+       prepare_inputs( nframes, offset );
+
        {
                Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
                if (lm.locked()) {
@@ -458,6 +463,7 @@ MidiTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
 
        nframes_t transport_frame = _session.transport_frame();
 
+       
        if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
                /* need to do this so that the diskstream sets its
                   playback distance to zero, thus causing diskstream::commit
@@ -511,6 +517,8 @@ MidiTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
        
        }
 
+       flush_outputs( nframes, offset );
+
        return 0;
 }
 
index c616a6fe008b6b1c2c555e0cbb8b3bc4eceacc3f..6a6a84040718a0e6ee2252cdb52dd3f4228d9ff9 100644 (file)
@@ -1000,6 +1000,7 @@ Panner::set_state (const XMLNode& node)
        XMLNodeConstIterator niter;
        const XMLProperty *prop;
        uint32_t i;
+       uint32_t num_panners = 0;
        StreamPanner* sp;
        LocaleGuard lg (X_("POSIX"));
 
@@ -1022,15 +1023,6 @@ Panner::set_state (const XMLNode& node)
                set_bypassed (prop->value() == "yes");
        }
     
-    if ((prop = node.property (X_("ins"))) != 0) {
-        ins.set_audio(atoi(prop->value().c_str()));
-    }
-    
-    if ((prop = node.property (X_("outs"))) != 0) {
-        outs.set_audio(atoi(prop->value().c_str()));
-    }
-    
-
        if ((prop = node.property (X_("link_direction"))) != 0) {
                LinkDirection ld; /* here to provide type information */
                set_link_direction (LinkDirection (string_2_enum (prop->value(), ld)));
@@ -1068,7 +1060,8 @@ Panner::set_state (const XMLNode& node)
                                                   assumption, but its still an assumption.
                                                */
                                                
-                                               sp = pan_plugins[i].factory (*this, Evoral::Parameter(PanAutomation, 0, i));
+                                               sp = pan_plugins[i].factory (*this, Evoral::Parameter(PanAutomation, 0, num_panners));
+                                               num_panners++;
                                                
                                                if (sp->set_state (**niter) == 0) {
                                                        _streampanners.push_back (sp);
@@ -1094,7 +1087,7 @@ Panner::set_state (const XMLNode& node)
                }       
        }
 
-       reset(ins.n_audio(), outs.n_audio());
+       reset(num_panners, outputs.size());
        /* don't try to do old-school automation loading if it wasn't marked as existing */
 
        if ((prop = node.property (X_("automation")))) {
index 5433120f531c424c9e7da18add8f79c0f6ef7e05..5a28fd5890c6b8d26f1efcb7abf7c1ada1fa022e 100644 (file)
@@ -50,6 +50,10 @@ using namespace std;
 void
 Session::process (nframes_t nframes)
 {
+       // This is no more the appriopriate place to call cycle
+       // start. cycle_start needs to be called at the Route::roll()
+       // where the signals which we want to mixdown have been calculated.
+       //
        MIDI::Manager::instance()->cycle_start(nframes);
 
        _silent = false;