Fix deletion of VCA with slaved controls.
[ardour.git] / libs / ardour / audio_diskstream.cc
index 5d390723d1a5ff4446b203a9aa2d6bc0ead5d45a..b2bf7b2b4a8fedffd56ea70d6bb67e1c68fb37e1 100644 (file)
@@ -27,7 +27,7 @@
 #include <cstdlib>
 #include <ctime>
 
-#include <pbd/gstdio_compat.h>
+#include "pbd/gstdio_compat.h"
 #include "pbd/error.h"
 #include "pbd/xml++.h"
 #include "pbd/memento_command.h"
@@ -56,7 +56,7 @@
 #include "ardour/types.h"
 #include "ardour/utils.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 #include <locale.h>
 
 using namespace std;
@@ -168,7 +168,7 @@ AudioDiskstream::non_realtime_input_change ()
                        need_write_sources = true;
                }
 
-               if (input_change_pending.type == IOChange::ConfigurationChanged) {
+               if (input_change_pending.type & IOChange::ConfigurationChanged) {
                        RCUWriter<ChannelList> writer (channels);
                        boost::shared_ptr<ChannelList> c = writer.get_copy();
 
@@ -316,6 +316,7 @@ AudioDiskstream::use_copy_playlist ()
        newname = Playlist::bump_name (_playlist->name(), _session);
 
        if ((playlist = boost::dynamic_pointer_cast<AudioPlaylist>(PlaylistFactory::create (audio_playlist(), newname))) != 0) {
+               playlist->reset_shares();
                return use_playlist (playlist);
        } else {
                return -1;
@@ -359,8 +360,9 @@ AudioDiskstream::use_destructive_playlist ()
 
        boost::shared_ptr<Region> rp;
        {
-               const RegionList& rl (_playlist->region_list().rlist());
+               const RegionList& rl (_playlist->region_list_property().rlist());
                if (rl.size() > 0) {
+                       /* this can happen when dragging a region onto a tape track */
                        assert((rl.size() == 1));
                        rp = rl.front();
                }
@@ -377,9 +379,9 @@ AudioDiskstream::use_destructive_playlist ()
                throw failed_constructor();
        }
 
-       /* be sure to stretch the region out to the maximum length */
+       /* be sure to stretch the region out to the maximum length (non-musical)*/
 
-       region->set_length (max_framepos - region->position());
+       region->set_length (max_framepos - region->position(), 0);
 
        uint32_t n;
        ChannelList::iterator chan;
@@ -392,7 +394,12 @@ AudioDiskstream::use_destructive_playlist ()
 
                /* this might be false if we switched modes, so force it */
 
+#ifdef XXX_OLD_DESTRUCTIVE_API_XXX
                (*chan)->write_source->set_destructive (true);
+#else
+               // should be set when creating the source or loading the state
+               assert ((*chan)->write_source->destructive());
+#endif
        }
 
        /* the source list will never be reset for a destructive track */
@@ -1634,6 +1641,7 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
                _playlist->set_capture_insertion_in_progress (true);
                _playlist->freeze ();
 
+               const framepos_t preroll_off = _session.preroll_record_trim_len ();
                for (buffer_position = c->front()->write_source->last_capture_start_frame(), ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
 
                        string region_name;
@@ -1653,6 +1661,9 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
 
                                boost::shared_ptr<Region> rx (RegionFactory::create (srcs, plist));
                                region = boost::dynamic_pointer_cast<AudioRegion> (rx);
+                               if (preroll_off > 0) {
+                                       region->trim_front (buffer_position + preroll_off);
+                               }
                        }
 
                        catch (failed_constructor& err) {
@@ -1662,7 +1673,7 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
 
                        i_am_the_modifier++;
 
-                       _playlist->add_region (region, (*ci)->start, 1, non_layered());
+                       _playlist->add_region (region, (*ci)->start + preroll_off, 1, non_layered());
                        _playlist->set_layer (region, DBL_MAX);
                        i_am_the_modifier--;
 
@@ -1894,12 +1905,10 @@ XMLNode&
 AudioDiskstream::get_state ()
 {
        XMLNode& node (Diskstream::get_state());
-       char buf[64] = "";
-       LocaleGuard lg (X_("C"));
+       LocaleGuard lg;
 
        boost::shared_ptr<ChannelList> c = channels.reader();
-       snprintf (buf, sizeof(buf), "%u", (unsigned int) c->size());
-       node.add_property ("channels", buf);
+       node.set_property ("channels", (uint32_t)c->size());
 
        if (!capturing_sources.empty() && _session.get_record_enabled()) {
 
@@ -1908,7 +1917,7 @@ AudioDiskstream::get_state ()
 
                for (vector<boost::shared_ptr<AudioFileSource> >::iterator i = capturing_sources.begin(); i != capturing_sources.end(); ++i) {
                        cs_grandchild = new XMLNode (X_("file"));
-                       cs_grandchild->add_property (X_("path"), (*i)->path());
+                       cs_grandchild->set_property (X_("path"), (*i)->path());
                        cs_child->add_child_nocopy (*cs_grandchild);
                }
 
@@ -1916,13 +1925,14 @@ AudioDiskstream::get_state ()
 
                Location* pi;
 
-               if (_session.config.get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
-                       snprintf (buf, sizeof (buf), "%" PRId64, pi->start());
+               if (_session.preroll_record_punch_enabled ()) {
+                       cs_child->set_property (X_("at"), _session.preroll_record_punch_pos());
+               } else if (_session.config.get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
+                       cs_child->set_property (X_("at"), pi->start());
                } else {
-                       snprintf (buf, sizeof (buf), "%" PRId64, _session.transport_frame());
+                       cs_child->set_property (X_("at"), _session.transport_frame());
                }
 
-               cs_child->add_property (X_("at"), buf);
                node.add_child_nocopy (*cs_child);
        }
 
@@ -1932,12 +1942,10 @@ AudioDiskstream::get_state ()
 int
 AudioDiskstream::set_state (const XMLNode& node, int version)
 {
-       const XMLProperty* prop;
        XMLNodeList nlist = node.children();
        XMLNodeIterator niter;
-       uint32_t nchans = 1;
        XMLNode* capture_pending_node = 0;
-       LocaleGuard lg (X_("C"));
+       LocaleGuard lg;
 
        /* prevent write sources from being created */
 
@@ -1957,9 +1965,8 @@ AudioDiskstream::set_state (const XMLNode& node, int version)
                return -1;
        }
 
-       if ((prop = node.property ("channels")) != 0) {
-               nchans = atoi (prop->value().c_str());
-       }
+       uint32_t nchans = 1;
+       node.get_property ("channels", nchans);
 
        // create necessary extra channels
        // we are always constructed with one and we always need one
@@ -1976,8 +1983,6 @@ AudioDiskstream::set_state (const XMLNode& node, int version)
                remove_channel (_n_channels.n_audio() - nchans);
        }
 
-
-
        if (!destructive() && capture_pending_node) {
                /* destructive streams have one and only one source per channel,
                   and so they never end up in pending capture in any useful
@@ -2174,6 +2179,22 @@ AudioDiskstream::set_align_style_from_io ()
                }
        }
 
+#ifdef MIXBUS
+       // compensate for latency when bouncing from master or mixbus.
+       // we need to use "ExistingMaterial" to pick up the master bus' latency
+       // see also Route::direct_feeds_according_to_reality
+       IOVector ios;
+       ios.push_back (_io);
+       if (_session.master_out() && ios.fed_by (_session.master_out()->output())) {
+               have_physical = true;
+       }
+       for (uint32_t n = 0; n < NUM_MIXBUSES && !have_physical; ++n) {
+               if (_session.get_mixbus (n) && ios.fed_by (_session.get_mixbus(n)->output())) {
+                       have_physical = true;
+               }
+       }
+#endif
+
        if (have_physical) {
                set_align_style (ExistingMaterial);
        } else {
@@ -2237,11 +2258,11 @@ AudioDiskstream::playback_buffer_load () const
        boost::shared_ptr<ChannelList> c = channels.reader();
 
        if (c->empty ()) {
-               return 0;
+               return 1.0;
        }
 
        return (float) ((double) c->front()->playback_buf->read_space()/
-                       (double) c->front()->playback_buf->bufsize());
+                          (double) c->front()->playback_buf->bufsize());
 }
 
 float
@@ -2250,7 +2271,7 @@ AudioDiskstream::capture_buffer_load () const
        boost::shared_ptr<ChannelList> c = channels.reader();
 
        if (c->empty ()) {
-               return 0;
+               return 1.0;
        }
 
        return (float) ((double) c->front()->capture_buf->write_space()/
@@ -2260,7 +2281,7 @@ AudioDiskstream::capture_buffer_load () const
 int
 AudioDiskstream::use_pending_capture_data (XMLNode& node)
 {
-       const XMLProperty* prop;
+       XMLProperty const * prop;
        XMLNodeList nlist = node.children();
        XMLNodeIterator niter;
        boost::shared_ptr<AudioFileSource> fs;
@@ -2368,6 +2389,7 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
        return 0;
 }
 
+#ifdef XXX_OLD_DESTRUCTIVE_API_XXX
 int
 AudioDiskstream::set_non_layered (bool yn)
 {
@@ -2435,7 +2457,7 @@ AudioDiskstream::can_become_destructive (bool& requires_bounce) const
 
        boost::shared_ptr<Region> first;
        {
-               const RegionList& rl (_playlist->region_list().rlist());
+               const RegionList& rl (_playlist->region_list_property().rlist());
                assert((rl.size() == 1));
                first = rl.front();
 
@@ -2481,6 +2503,7 @@ AudioDiskstream::can_become_destructive (bool& requires_bounce) const
        requires_bounce = false;
        return true;
 }
+#endif
 
 void
 AudioDiskstream::adjust_playback_buffering ()