Fixes to bundle manager to make it vaguely usable.
[ardour.git] / libs / ardour / audio_track.cc
index cd05e5fc86b6200c1d7fa52288bf111e657e0b46..5749afd265a06537ef80a49c006fb63cf109f8b7 100644 (file)
@@ -39,6 +39,8 @@
 #include <ardour/panner.h>
 #include <ardour/utils.h>
 #include <ardour/buffer_set.h>
+#include <ardour/audio_buffer.h>
+#include <ardour/internal_send.h>
 #include "i18n.h"
 
 using namespace std;
@@ -64,6 +66,8 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode
        
        _session.add_diskstream (ds);
 
+       _session.RouteAdded.connect (mem_fun (*this, &AudioTrack::catch_up_on_busses));
+
        set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (ds), this);
 }
 
@@ -71,12 +75,47 @@ AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
        : Track (sess, node)
 {
        _set_state (node, false);
+
+       _session.RouteAdded.connect (mem_fun (*this, &AudioTrack::catch_up_on_busses));
 }
 
 AudioTrack::~AudioTrack ()
 {
 }
 
+void
+AudioTrack::catch_up_on_busses (RouteList& added)
+{
+       if (is_hidden()) {
+               return;
+       }
+
+       for (RouteList::iterator x = added.begin(); x != added.end(); ++x) {
+               if (boost::dynamic_pointer_cast<Track>(*x) == 0 && (*x)->default_type() == DataType::AUDIO)  {
+                       /* Audio bus */
+                       if (!(*x)->is_master() && !(*x)->is_control()) {
+                               add_internal_send (*x);
+                       }
+               }
+       }
+}
+
+void
+AudioTrack::add_internal_send (boost::shared_ptr<Route> r)
+{
+       boost::shared_ptr<InternalSend> is (new InternalSend (_session, PreFader, r));
+
+       cerr << name() << " Adding processor\n";
+       
+       add_processor (is, 0);
+
+       cerr << "After add, we have " << _processors.size() << endl;
+               
+       /* note: if adding failed, the InternalSend will be cleaned up automatically when
+          the shared_ptr goes out of scope.
+       */
+}
+
 int
 AudioTrack::set_mode (TrackMode m)
 {
@@ -540,6 +579,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
@@ -584,19 +625,74 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
 
                
                /* copy the diskstream data to all output buffers */
-               
-               const size_t limit = n_process_buffers().n_audio();
-               BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
-               
+
+               size_t limit = n_process_buffers().n_audio();
+               BufferSet& bufs = _session.get_scratch_buffers ();
+               const size_t blimit = bufs.count().n_audio();
+
                uint32_t n;
                uint32_t i;
 
-               for (i = 0, n = 1; i < limit; ++i, ++n) {
-                       memcpy (bufs.get_audio(i).data(), b, sizeof (Sample) * nframes); 
-                       if (n < diskstream->n_channels().n_audio()) {
-                               tmpb = diskstream->playback_buffer(n);
-                               if (tmpb!=0) {
-                                       b = tmpb;
+               if (limit > blimit) {
+
+                       /* example case: auditioner configured for stereo output,
+                          but loaded with an 8 channel file. there are only
+                          2 passthrough buffers, but n_process_buffers() will
+                          return 8.
+                          
+                          arbitrary decision: map all channels in the diskstream
+                          to the outputs available.
+                       */
+
+                       float scaling = limit/blimit;
+                       
+                       for (i = 0, n = 1; i < blimit; ++i, ++n) {
+
+                               /* first time through just copy a channel into 
+                                  the output buffer.
+                               */
+                               
+                               Sample* bb = bufs.get_audio (i).data();
+
+                               for (nframes_t xx = 0; xx < nframes; ++xx) {
+                                       bb[xx] = b[xx] * scaling;
+                               }
+
+                               if (n < diskstream->n_channels().n_audio()) {
+                                       tmpb = diskstream->playback_buffer(n);
+                                       if (tmpb!=0) {
+                                               b = tmpb;
+                                       }
+                               }
+                       }
+
+                       for (;i < limit; ++i, ++n) {
+                               
+                               /* for all remaining channels, sum with existing
+                                  data in the output buffers 
+                               */
+                               
+                               bufs.get_audio (i%blimit).accumulate_with_gain_from (b, nframes, 0, scaling);
+                               
+                               if (n < diskstream->n_channels().n_audio()) {
+                                       tmpb = diskstream->playback_buffer(n);
+                                       if (tmpb!=0) {
+                                               b = tmpb;
+                                       }
+                               }
+                               
+                       }
+
+                       limit = blimit;
+
+               } else {
+                       for (i = 0, n = 1; i < blimit; ++i, ++n) {
+                               memcpy (bufs.get_audio (i).data(), b, sizeof (Sample) * nframes); 
+                               if (n < diskstream->n_channels().n_audio()) {
+                                       tmpb = diskstream->playback_buffer(n);
+                                       if (tmpb!=0) {
+                                               b = tmpb;
+                                       }
                                }
                        }
                }
@@ -604,9 +700,9 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
                /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
 
                if (!diskstream->record_enabled() && _session.transport_rolling()) {
-                       Glib::Mutex::Lock am (_automation_lock, Glib::TRY_LOCK);
+                       Glib::Mutex::Lock am (data().control_lock(), Glib::TRY_LOCK);
                        
-                       if (am.locked() && gain_control()->list()->automation_playback()) {
+                       if (am.locked() && gain_control()->automation_playback()) {
                                apply_gain_automation = gain_control()->list()->curve().rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
                        }
                }
@@ -702,7 +798,7 @@ AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes
                }
        }
        
-       if (gain_control()->list()->automation_state() == Play) {
+       if (gain_control()->automation_state() == Play) {
                
                gain_control()->list()->curve().get_vector (start, start + nframes, gain_automation, nframes);
 
@@ -821,13 +917,18 @@ AudioTrack::freeze (InterThreadInfo& itt)
                                
                                /* now deactivate the processor */
                                
-                               processor->set_active (false);
+                               processor->deactivate ();
                                _session.set_dirty ();
                        }
                }
        }
 
        new_playlist = PlaylistFactory::create (DataType::AUDIO, _session, new_playlist_name, false);
+
+       _freeze_record.gain = _gain;
+       _freeze_record.gain_automation_state = _gain_control->automation_state();
+       _freeze_record.pan_automation_state = _panner->automation_state();
+
        region_name = new_playlist_name;
 
        /* create a new region from all filesources, keep it private */
@@ -845,6 +946,12 @@ AudioTrack::freeze (InterThreadInfo& itt)
        diskstream->use_playlist (boost::dynamic_pointer_cast<AudioPlaylist>(new_playlist));
        diskstream->set_record_enabled (false);
 
+       /* reset stuff that has already been accounted for in the freeze process */
+       
+       set_gain (1.0, this);
+       _gain_control->set_automation_state (Off);
+       _panner->set_automation_state (Off);
+
        _freeze_record.state = Frozen;
        FreezeChange(); /* EMIT SIGNAL */
 }
@@ -875,6 +982,9 @@ AudioTrack::unfreeze ()
                }
                
                _freeze_record.playlist.reset ();
+               set_gain (_freeze_record.gain, this);
+               _gain_control->set_automation_state (_freeze_record.gain_automation_state);
+               _panner->set_automation_state (_freeze_record.pan_automation_state);
        }
 
        _freeze_record.state = UnFrozen;