permit different sizes for audio playback & capture buffers
[ardour.git] / libs / ardour / audioregion.cc
index d1e78cadd32d78ab8bc082e4dcebd277d43c345a..0ef79b7018807e234b0c64201c80f009f4893d77 100644 (file)
@@ -36,6 +36,7 @@
 #include "evoral/Curve.hpp"
 
 #include "ardour/audioregion.h"
+#include "ardour/debug.h"
 #include "ardour/session.h"
 #include "ardour/gain.h"
 #include "ardour/dB.h"
@@ -52,218 +53,199 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
-/* a Session will reset these to its chosen defaults by calling AudioRegion::set_default_fade() */
+namespace ARDOUR {
+       namespace Properties {
+               PBD::PropertyDescriptor<bool> envelope_active;
+               PBD::PropertyDescriptor<bool> default_fade_in;
+               PBD::PropertyDescriptor<bool> default_fade_out;
+               PBD::PropertyDescriptor<bool> fade_in_active;
+               PBD::PropertyDescriptor<bool> fade_out_active;
+               PBD::PropertyDescriptor<float> scale_amplitude;
+       }
+}
 
-Change AudioRegion::FadeInChanged         = PBD::new_change();
-Change AudioRegion::FadeOutChanged        = PBD::new_change();
-Change AudioRegion::FadeInActiveChanged   = PBD::new_change();
-Change AudioRegion::FadeOutActiveChanged  = PBD::new_change();
-Change AudioRegion::EnvelopeActiveChanged = PBD::new_change();
-Change AudioRegion::ScaleAmplitudeChanged = PBD::new_change();
-Change AudioRegion::EnvelopeChanged       = PBD::new_change();
+void
+AudioRegion::make_property_quarks ()
+{
+       Properties::envelope_active.property_id = g_quark_from_static_string (X_("envelope-active"));
+        DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for envelope-active = %1\n",    Properties::envelope_active.property_id));
+       Properties::default_fade_in.property_id = g_quark_from_static_string (X_("default-fade-in"));
+        DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for default-fade-in = %1\n",    Properties::default_fade_in.property_id));
+       Properties::default_fade_out.property_id = g_quark_from_static_string (X_("default-fade-out"));
+        DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for default-fade-out = %1\n",   Properties::default_fade_out.property_id));
+       Properties::fade_in_active.property_id = g_quark_from_static_string (X_("fade-in-active"));
+        DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade-in-active = %1\n",     Properties::fade_in_active.property_id));
+       Properties::fade_out_active.property_id = g_quark_from_static_string (X_("fade-out-active"));
+        DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade-out-active = %1\n",    Properties::fade_out_active.property_id));
+       Properties::scale_amplitude.property_id = g_quark_from_static_string (X_("scale-amplitude"));
+        DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for scale-amplitude = %1\n",    Properties::scale_amplitude.property_id));
+}
+
+void
+AudioRegion::register_properties ()
+{
+       /* no need to register parent class properties */
+
+       add_property (_envelope_active);
+       add_property (_default_fade_in);
+       add_property (_default_fade_out);
+       add_property (_fade_in_active);
+       add_property (_fade_out_active);
+       add_property (_scale_amplitude);
+}
+
+#define AUDIOREGION_STATE_DEFAULT \
+       _envelope_active (Properties::envelope_active, false) \
+       , _default_fade_in (Properties::default_fade_in, true) \
+       , _default_fade_out (Properties::default_fade_out, true) \
+       , _fade_in_active (Properties::fade_in_active, true) \
+       , _fade_out_active (Properties::fade_out_active, true) \
+       , _scale_amplitude (Properties::scale_amplitude, 1.0)
+
+#define AUDIOREGION_COPY_STATE(other) \
+        _envelope_active (other->_envelope_active) \
+       , _default_fade_in (other->_default_fade_in) \
+       , _default_fade_out (other->_default_fade_out) \
+        , _fade_in_active (other->_fade_in_active) \
+        , _fade_out_active (other->_fade_out_active) \
+       , _scale_amplitude (other->_scale_amplitude) 
+
+/* a Session will reset these to its chosen defaults by calling AudioRegion::set_default_fade() */
 
 void
 AudioRegion::init ()
 {
-       _scale_amplitude = 1.0;
+       register_properties ();
 
        set_default_fades ();
        set_default_envelope ();
 
        listen_to_my_curves ();
        connect_to_analysis_changed ();
+       connect_to_header_position_offset_changed ();
 }
 
 /** Constructor for use by derived types only */
-AudioRegion::AudioRegion (Session& s, nframes_t start, nframes_t length, string name)
-       : Region (s, start, length, name, DataType::AUDIO)
-       , _automatable(s)
-       , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
-       , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
-       , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
-{
-       init ();
-       assert (_sources.size() == _master_sources.size());
-}
-
-/** Basic AudioRegion constructor (one channel) */
-AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, nframes_t length)
-       : Region (src, start, length, PBD::basename_nosuffix(src->name()), DataType::AUDIO, 0,  Region::Flag(Region::DefaultFlags|Region::External))
-       , _automatable(src->session())
+AudioRegion::AudioRegion (Session& s, framepos_t start, framecnt_t len, std::string name)
+       : Region (s, start, len, name, DataType::AUDIO)
+       , AUDIOREGION_STATE_DEFAULT
+       , _automatable (s)
        , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
        , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
        , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
+       , _fade_in_suspended (0)
+       , _fade_out_suspended (0)
 {
-       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
-       if (afs) {
-               afs->HeaderPositionOffsetChanged.connect_same_thread (*this, boost::bind (&AudioRegion::source_offset_changed, this));
-       }
-
        init ();
        assert (_sources.size() == _master_sources.size());
 }
 
-/* Basic AudioRegion constructor (one channel) */
-AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags)
-       : Region (src, start, length, name, DataType::AUDIO, layer, flags)
-       , _automatable(src->session())
-       , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
-       , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
-       , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
-{
-       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
-       if (afs) {
-               afs->HeaderPositionOffsetChanged.connect_same_thread (*this, boost::bind (&AudioRegion::source_offset_changed, this));
-       }
-
-       init ();
-       assert (_sources.size() == _master_sources.size());
-}
-
-/** Basic AudioRegion constructor (many channels) */
-AudioRegion::AudioRegion (const SourceList& srcs, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags)
-       : Region (srcs, start, length, name, DataType::AUDIO, layer, flags)
+/** Basic AudioRegion constructor */
+AudioRegion::AudioRegion (const SourceList& srcs)
+       : Region (srcs)
+       , AUDIOREGION_STATE_DEFAULT
        , _automatable(srcs[0]->session())
        , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
        , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
        , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
+       , _fade_in_suspended (0)
+       , _fade_out_suspended (0)
 {
        init ();
-       connect_to_analysis_changed ();
        assert (_sources.size() == _master_sources.size());
 }
 
-/** Create a new AudioRegion, that is part of an existing one */
-AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes_t offset, nframes_t length, const string& name, layer_t layer, Flag flags)
-       : Region (other, offset, length, name, layer, flags)
-       , _automatable(other->session())
-       , _fade_in (new AutomationList(*other->_fade_in))
-       , _fade_out (new AutomationList(*other->_fade_out))
-       , _envelope (new AutomationList(*other->_envelope, offset, offset + length))
-{
-       connect_to_header_position_offset_changed ();
-
-       /* return to default fades if the existing ones are too long */
-
-       if (_flags & LeftOfSplit) {
-               if (_fade_in->back()->when >= _length) {
-                       set_default_fade_in ();
-               } else {
-                       _fade_in_disabled = other->_fade_in_disabled;
-               }
-               set_default_fade_out ();
-               _flags = Flag (_flags & ~Region::LeftOfSplit);
-       }
-
-       if (_flags & RightOfSplit) {
-               if (_fade_out->back()->when >= _length) {
-                       set_default_fade_out ();
-               } else {
-                       _fade_out_disabled = other->_fade_out_disabled;
-               }
-               set_default_fade_in ();
-               _flags = Flag (_flags & ~Region::RightOfSplit);
-       }
-
-       _scale_amplitude = other->_scale_amplitude;
-
-       assert(_type == DataType::AUDIO);
-
-       listen_to_my_curves ();
-       connect_to_analysis_changed ();
-
-       assert (_sources.size() == _master_sources.size());
-}
-
-AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
-       : Region (other)
+AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes64_t offset, bool offset_relative)
+       : Region (other, offset, offset_relative)
+       , AUDIOREGION_COPY_STATE (other)
        , _automatable (other->session())
        , _fade_in (new AutomationList (*other->_fade_in))
        , _fade_out (new AutomationList (*other->_fade_out))
-       , _envelope (new AutomationList (*other->_envelope))
+         /* XXX is this guaranteed to work for all values of offset+offset_relative? */
+       , _envelope (new AutomationList (*other->_envelope, _start, _start + _length))
+       , _fade_in_suspended (0)
+       , _fade_out_suspended (0)
 {
-       assert(_type == DataType::AUDIO);
-       _scale_amplitude = other->_scale_amplitude;
-
+       /* don't use init here, because we got fade in/out from the other region
+       */
+       register_properties ();
        listen_to_my_curves ();
        connect_to_analysis_changed ();
+       connect_to_header_position_offset_changed ();
 
+       assert(_type == DataType::AUDIO);
        assert (_sources.size() == _master_sources.size());
 }
 
-AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, const SourceList& /*srcs*/,
-                         nframes_t length, const string& name, layer_t layer, Flag flags)
-       : Region (other, length, name, layer, flags)
+AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, const SourceList& srcs)
+       : Region (boost::static_pointer_cast<const Region>(other), srcs)
+       , AUDIOREGION_COPY_STATE (other)
        , _automatable (other->session())
        , _fade_in (new AutomationList (*other->_fade_in))
        , _fade_out (new AutomationList (*other->_fade_out))
        , _envelope (new AutomationList (*other->_envelope))
+       , _fade_in_suspended (0)
+       , _fade_out_suspended (0)
 {
        /* make-a-sort-of-copy-with-different-sources constructor (used by audio filter) */
 
-       for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
-
-               boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> ((*i));
-               if (afs) {
-                       afs->HeaderPositionOffsetChanged.connect_same_thread (*this, boost::bind (&AudioRegion::source_offset_changed, this));
-               }
-       }
-
-       _scale_amplitude = other->_scale_amplitude;
-
-       _fade_in_disabled = 0;
-       _fade_out_disabled = 0;
+       register_properties ();
 
        listen_to_my_curves ();
        connect_to_analysis_changed ();
+       connect_to_header_position_offset_changed ();
 
        assert (_sources.size() == _master_sources.size());
 }
 
-AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& node)
-       : Region (src, node)
-       , _automatable(src->session())
+AudioRegion::AudioRegion (SourceList& srcs)
+       : Region (srcs)
+       , AUDIOREGION_STATE_DEFAULT
+       , _automatable(srcs[0]->session())
        , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
        , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
        , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
+       , _fade_in_suspended (0)
+       , _fade_out_suspended (0)
 {
-       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
-       if (afs) {
-               afs->HeaderPositionOffsetChanged.connect_same_thread (*this, boost::bind (&AudioRegion::source_offset_changed, this));
-       }
-
        init ();
 
-       if (set_state (node, Stateful::loading_state_version)) {
-               throw failed_constructor();
-       }
-
        assert(_type == DataType::AUDIO);
-       connect_to_analysis_changed ();
-
        assert (_sources.size() == _master_sources.size());
 }
 
-AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
-       : Region (srcs, node)
-       , _automatable(srcs[0]->session())
-       , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
-       , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
-       , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
+AudioRegion::~AudioRegion ()
 {
-       init ();
+}
 
-       if (set_state (node, Stateful::loading_state_version)) {
-               throw failed_constructor();
+void
+AudioRegion::post_set ()
+{
+       if (!_sync_marked) {
+               _sync_position = _start;
        }
 
-       assert(_type == DataType::AUDIO);
-       connect_to_analysis_changed ();
-       assert (_sources.size() == _master_sources.size());
-}
+       /* return to default fades if the existing ones are too long */
 
-AudioRegion::~AudioRegion ()
-{
+       if (_left_of_split) {
+               if (_fade_in->back()->when >= _length) {
+                       set_default_fade_in ();
+               } 
+               set_default_fade_out ();
+               _left_of_split = false;
+       }
+
+       if (_right_of_split) {
+               if (_fade_out->back()->when >= _length) {
+                       set_default_fade_out ();
+               } 
+
+               set_default_fade_in ();
+               _right_of_split = false;
+       }
+
+       /* If _length changed, adjust our gain envelope accordingly */
+       _envelope->truncate_end (_length);
 }
 
 void
@@ -294,8 +276,6 @@ AudioRegion::connect_to_header_position_offset_changed ()
 void
 AudioRegion::listen_to_my_curves ()
 {
-       cerr << _name << ": listeing my own curves\n";
-
        _envelope->StateChanged.connect_same_thread (*this, boost::bind (&AudioRegion::envelope_changed, this));
        _fade_in->StateChanged.connect_same_thread (*this, boost::bind (&AudioRegion::fade_in_changed, this));
        _fade_out->StateChanged.connect_same_thread (*this, boost::bind (&AudioRegion::fade_out_changed, this));
@@ -305,12 +285,8 @@ void
 AudioRegion::set_envelope_active (bool yn)
 {
        if (envelope_active() != yn) {
-               if (yn) {
-                       _flags = Flag (_flags|EnvelopeActive);
-               } else {
-                       _flags = Flag (_flags & ~EnvelopeActive);
-               }
-               send_change (EnvelopeActiveChanged);
+               _envelope_active = yn;
+               send_change (PropertyChange (Properties::envelope_active));
        }
 }
 
@@ -324,7 +300,7 @@ AudioRegion::read_peaks (PeakData *buf, nframes_t npeaks, nframes_t offset, nfra
        if (audio_source(chan_n)->read_peaks (buf, npeaks, offset, cnt, samples_per_unit)) {
                return 0;
        } else {
-               if (_scale_amplitude != 1.0) {
+               if (_scale_amplitude != 1.0f) {
                        for (nframes_t n = 0; n < npeaks; ++n) {
                                buf[n].max *= _scale_amplitude;
                                buf[n].min *= _scale_amplitude;
@@ -334,32 +310,26 @@ AudioRegion::read_peaks (PeakData *buf, nframes_t npeaks, nframes_t offset, nfra
        }
 }
 
-nframes_t
-AudioRegion::read (Sample* buf, sframes_t timeline_position, nframes_t cnt, int channel) const
+framecnt_t
+AudioRegion::read (Sample* buf, framepos_t timeline_position, framecnt_t cnt, int channel) const
 {
        /* raw read, no fades, no gain, nada */
        return _read_at (_sources, _length, buf, 0, 0, _position + timeline_position, cnt, channel, 0, 0, ReadOps (0));
 }
 
-nframes_t
-AudioRegion::read_with_ops (Sample* buf, sframes_t file_position, nframes_t cnt, int channel, ReadOps rops) const
-{
-       return _read_at (_sources, _length, buf, 0, 0, file_position, cnt, channel, 0, 0, rops);
-}
-
-nframes_t
+framecnt_t
 AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
-               sframes_t file_position, nframes_t cnt, uint32_t chan_n,
-               nframes_t read_frames, nframes_t skip_frames) const
+                     framepos_t file_position, framecnt_t cnt, uint32_t chan_n,
+                     framecnt_t read_frames, framecnt_t skip_frames) const
 {
        /* regular diskstream/butler read complete with fades etc */
        return _read_at (_sources, _length, buf, mixdown_buffer, gain_buffer,
                        file_position, cnt, chan_n, read_frames, skip_frames, ReadOps (~0));
 }
 
-nframes_t
+framecnt_t
 AudioRegion::master_read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
-               sframes_t position, nframes_t cnt, uint32_t chan_n) const
+                            framepos_t position, framecnt_t cnt, uint32_t chan_n) const
 {
        /* do not read gain/scaling/fades and do not count this disk i/o in statistics */
 
@@ -367,18 +337,19 @@ AudioRegion::master_read_at (Sample *buf, Sample *mixdown_buffer, float *gain_bu
                         buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, 0, 0, ReadOps (0));
 }
 
-nframes_t
-AudioRegion::_read_at (const SourceList& /*srcs*/, nframes_t limit,
-               Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
-               sframes_t position, nframes_t cnt,
-               uint32_t chan_n,
-               nframes_t /*read_frames*/,
-               nframes_t /*skip_frames*/,
-               ReadOps rops) const
+framecnt_t
+AudioRegion::_read_at (const SourceList& /*srcs*/, framecnt_t limit,
+                      Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
+                      framepos_t position, 
+                      framecnt_t cnt,
+                      uint32_t chan_n,
+                      framecnt_t /*read_frames*/,
+                      framecnt_t /*skip_frames*/,
+                      ReadOps rops) const
 {
-       nframes_t internal_offset;
-       nframes_t buf_offset;
-       nframes_t to_read;
+       frameoffset_t internal_offset;
+       frameoffset_t buf_offset;
+       framecnt_t to_read;
        bool raw = (rops == ReadOpsNone);
 
        if (muted() && !raw) {
@@ -439,7 +410,7 @@ AudioRegion::_read_at (const SourceList& /*srcs*/, nframes_t limit,
 
                /* fade in */
 
-               if ((_flags & FadeIn) && _session.config.get_use_region_fades()) {
+               if (_fade_in_active && _session.config.get_use_region_fades()) {
 
                        nframes_t fade_in_length = (nframes_t) _fade_in->back()->when;
 
@@ -462,7 +433,7 @@ AudioRegion::_read_at (const SourceList& /*srcs*/, nframes_t limit,
 
                /* fade out */
 
-               if ((_flags & FadeOut) && _session.config.get_use_region_fades()) {
+               if (_fade_out_active && _session.config.get_use_region_fades()) {
 
                        /* see if some part of this read is within the fade out */
 
@@ -552,8 +523,6 @@ AudioRegion::state (bool full)
        char buf2[64];
        LocaleGuard lg (X_("POSIX"));
 
-       snprintf (buf, sizeof(buf), "%.12g", _scale_amplitude);
-       node.add_property ("scale-gain", buf);
 
        // XXX these should move into Region
 
@@ -573,26 +542,7 @@ AudioRegion::state (bool full)
        node.add_property ("channels", buf);
 
        if (full) {
-
-               child = node.add_child (X_("FadeIn"));
-
-               if ((_flags & DefaultFadeIn)) {
-                       child->add_property (X_("default"), X_("yes"));
-               } else {
-                       child->add_child_nocopy (_fade_in->get_state ());
-               }
-
-               child->add_property (X_("active"), fade_in_active () ? X_("yes") : X_("no"));
-
-               child = node.add_child (X_("FadeOut"));
-
-               if ((_flags & DefaultFadeOut)) {
-                       child->add_property (X_("default"), X_("yes"));
-               } else {
-                       child->add_child_nocopy (_fade_out->get_state ());
-               }
-
-               child->add_property (X_("active"), fade_out_active () ? X_("yes") : X_("no"));
+               Stateful::add_properties (node);
        }
 
        child = node.add_child ("Envelope");
@@ -629,44 +579,39 @@ AudioRegion::state (bool full)
 }
 
 int
-AudioRegion::set_live_state (const XMLNode& node, int version, Change& what_changed, bool send)
+AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_changed, bool send)
 {
        const XMLNodeList& nlist = node.children();
        const XMLProperty *prop;
        LocaleGuard lg (X_("POSIX"));
        boost::shared_ptr<Playlist> the_playlist (_playlist.lock());    
 
-       freeze ();
+       suspend_property_changes ();
+
        if (the_playlist) {
                the_playlist->freeze ();
        }
 
-       Region::set_live_state (node, version, what_changed, false);
-       cerr << "After region SLS, wc = " << what_changed << endl;
 
+       /* this will set all our State members and stuff controlled by the Region.
+          It should NOT send any changed signals - that is our responsibility.
+       */
 
-       if ((prop = node.property ("flags")) != 0) {
-               _flags = Flag (_flags & ~Region::LeftOfSplit);
-               _flags = Flag (_flags & ~Region::RightOfSplit);
-       }
-
-       /* find out if any flags changed that we signal about */
+       Region::_set_state (node, version, what_changed, false);
 
        if ((prop = node.property ("scale-gain")) != 0) {
                float a = atof (prop->value().c_str());
                if (a != _scale_amplitude) {
                        _scale_amplitude = a;
-                       what_changed = Change (what_changed|ScaleAmplitudeChanged);
-                       cerr << _name << " amp changed\n";
+                       what_changed.add (Properties::scale_amplitude);
                }
        }
 
-       /* Now find envelope description and other misc child items */
+       /* Now find envelope description and other related child items */
 
-       _envelope->freeze ();
+        _envelope->freeze ();
 
        for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
-#if 0
                XMLNode *child;
                XMLProperty *prop;
 
@@ -683,8 +628,6 @@ AudioRegion::set_live_state (const XMLNode& node, int version, Change& what_chan
                        _envelope->set_max_xval (_length);
                        _envelope->truncate_end (_length);
 
-                       cerr << _name << " envelope changd\n";
-               
 
                } else if (child->name() == "FadeIn") {
 
@@ -706,7 +649,6 @@ AudioRegion::set_live_state (const XMLNode& node, int version, Change& what_chan
                                        set_fade_in_active (false);
                                }
                        }
-                       cerr << _name << " fadein changd\n";
 
                } else if (child->name() == "FadeOut") {
 
@@ -728,17 +670,14 @@ AudioRegion::set_live_state (const XMLNode& node, int version, Change& what_chan
                                        set_fade_out_active (false);
                                }
                        }
-                       cerr << _name << " fadeout changd\n";
 
                }
-#endif
        }
 
-       _envelope->thaw ();
-       thaw ();
-
+        _envelope->thaw ();
+       resume_property_changes ();
+        
        if (send) {
-               cerr << _name << ": audio final change: " << hex << what_changed << dec << endl;
                send_change (what_changed);
        }
 
@@ -752,12 +691,8 @@ AudioRegion::set_live_state (const XMLNode& node, int version, Change& what_chan
 int
 AudioRegion::set_state (const XMLNode& node, int version)
 {
-       /* Region::set_state() calls the virtual set_live_state(),
-          which will get us back to AudioRegion::set_live_state()
-          to handle the relevant stuff.
-       */
-
-       return Region::set_state (node, version);
+       PropertyChange what_changed;
+       return _set_state (node, version, what_changed, true);
 }
 
 void
@@ -775,17 +710,17 @@ AudioRegion::set_fade_out_shape (FadeShape shape)
 void
 AudioRegion::set_fade_in (boost::shared_ptr<AutomationList> f)
 {
-       _fade_in->freeze ();
+        _fade_in->freeze ();
        *_fade_in = *f;
-       _fade_in->thaw ();
+        _fade_in->thaw ();
        
-       send_change (FadeInChanged);
+       send_change (PropertyChange (Properties::fade_in));
 }
 
 void
-AudioRegion::set_fade_in (FadeShape shape, nframes_t len)
+AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
 {
-       _fade_in->freeze ();
+        _fade_in->freeze ();
        _fade_in->clear ();
 
        switch (shape) {
@@ -836,23 +771,23 @@ AudioRegion::set_fade_in (FadeShape shape, nframes_t len)
                break;
        }
 
-       _fade_in->thaw ();
+        _fade_in->thaw ();
 }
 
 void
 AudioRegion::set_fade_out (boost::shared_ptr<AutomationList> f)
 {
-       _fade_out->freeze ();
+        _fade_out->freeze ();
        *_fade_out = *f;
-       _fade_out->thaw ();
+        _fade_out->thaw ();
 
-       send_change (FadeInChanged);
+       send_change (PropertyChange (Properties::fade_in));
 }
 
 void
-AudioRegion::set_fade_out (FadeShape shape, nframes_t len)
+AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
 {
-       _fade_out->freeze ();
+        _fade_out->freeze ();
        _fade_out->clear ();
 
        switch (shape) {
@@ -901,11 +836,11 @@ AudioRegion::set_fade_out (FadeShape shape, nframes_t len)
                break;
        }
 
-       _fade_out->thaw ();
+        _fade_out->thaw ();
 }
 
 void
-AudioRegion::set_fade_in_length (nframes_t len)
+AudioRegion::set_fade_in_length (framecnt_t len)
 {
        if (len > _length) {
                len = _length - 1;
@@ -914,13 +849,13 @@ AudioRegion::set_fade_in_length (nframes_t len)
        bool changed = _fade_in->extend_to (len);
 
        if (changed) {
-               _flags = Flag (_flags & ~DefaultFadeIn);
-               send_change (FadeInChanged);
+               _default_fade_in = false;
+               send_change (PropertyChange (Properties::fade_in));
        }
 }
 
 void
-AudioRegion::set_fade_out_length (nframes_t len)
+AudioRegion::set_fade_out_length (framecnt_t len)
 {
        if (len > _length) {
                len = _length - 1;
@@ -929,39 +864,30 @@ AudioRegion::set_fade_out_length (nframes_t len)
        bool changed =  _fade_out->extend_to (len);
 
        if (changed) {
-               _flags = Flag (_flags & ~DefaultFadeOut);
-               send_change (FadeOutChanged);
+               _default_fade_out = false;
+               send_change (PropertyChange (Properties::fade_out));
        }
 }
 
 void
 AudioRegion::set_fade_in_active (bool yn)
 {
-       if (yn == (_flags & FadeIn)) {
+       if (yn == _fade_in_active) {
                return;
        }
-       if (yn) {
-               _flags = Flag (_flags|FadeIn);
-       } else {
-               _flags = Flag (_flags & ~FadeIn);
-       }
 
-       send_change (FadeInActiveChanged);
+       _fade_in_active = yn;
+       send_change (PropertyChange (Properties::fade_in_active));
 }
 
 void
 AudioRegion::set_fade_out_active (bool yn)
 {
-       if (yn == (_flags & FadeOut)) {
+       if (yn == _fade_out_active) {
                return;
        }
-       if (yn) {
-               _flags = Flag (_flags | FadeOut);
-       } else {
-               _flags = Flag (_flags & ~FadeOut);
-       }
-
-       send_change (FadeOutActiveChanged);
+       _fade_out_active = yn;
+       send_change (PropertyChange (Properties::fade_out_active));
 }
 
 bool
@@ -979,14 +905,14 @@ AudioRegion::fade_out_is_default () const
 void
 AudioRegion::set_default_fade_in ()
 {
-       _fade_in_disabled = 0;
+       _fade_in_suspended = 0;
        set_fade_in (Linear, 64);
 }
 
 void
 AudioRegion::set_default_fade_out ()
 {
-       _fade_out_disabled = 0;
+       _fade_out_suspended = 0;
        set_fade_out (Linear, 64);
 }
 
@@ -1000,11 +926,11 @@ AudioRegion::set_default_fades ()
 void
 AudioRegion::set_default_envelope ()
 {
-       _envelope->freeze ();
+        _envelope->freeze ();
        _envelope->clear ();
        _envelope->fast_simple_add (0, 1.0f);
        _envelope->fast_simple_add (_length, 1.0f);
-       _envelope->thaw ();
+        _envelope->thaw ();
 }
 
 void
@@ -1014,19 +940,22 @@ AudioRegion::recompute_at_end ()
           based on the the existing curve.
        */
 
-       _envelope->freeze ();
+        _envelope->freeze ();
        _envelope->truncate_end (_length);
        _envelope->set_max_xval (_length);
-       _envelope->thaw ();
-
+        _envelope->thaw ();
+
+        if (_left_of_split) {
+                set_default_fade_out ();
+                _left_of_split = false;
+        } else if (_fade_out->back()->when > _length) {
+                _fade_out->extend_to (_length);
+                send_change (PropertyChange (Properties::fade_out));
+        }
+        
        if (_fade_in->back()->when > _length) {
                _fade_in->extend_to (_length);
-               send_change (FadeInChanged);
-       }
-
-       if (_fade_out->back()->when > _length) {
-               _fade_out->extend_to (_length);
-               send_change (FadeOutChanged);
+               send_change (PropertyChange (Properties::fade_in));
        }
 }
 
@@ -1037,14 +966,17 @@ AudioRegion::recompute_at_start ()
 
        _envelope->truncate_start (_length);
 
-       if (_fade_in->back()->when > _length) {
+        if (_right_of_split) {
+                set_default_fade_in ();
+                _right_of_split = false;
+        } else if (_fade_in->back()->when > _length) {
                _fade_in->extend_to (_length);
-               send_change (FadeInChanged);
+               send_change (PropertyChange (Properties::fade_in));
        }
 
        if (_fade_out->back()->when > _length) {
                _fade_out->extend_to (_length);
-               send_change (FadeOutChanged);
+               send_change (PropertyChange (Properties::fade_out));
        }
 }
 
@@ -1080,9 +1012,15 @@ AudioRegion::separate_by_channel (Session& /*session*/, vector<boost::shared_ptr
                   "whole file" even if it covers the entire source file(s).
                 */
 
-               Flag f = Flag (_flags & ~WholeFile);
+               PropertyList plist;
+               
+               plist.add (Properties::start, _start.val());
+               plist.add (Properties::length, _length.val());
+               plist.add (Properties::name, new_name);
+               plist.add (Properties::layer, _layer.val());
 
-               v.push_back(RegionFactory::create (srcs, _start, _length, new_name, _layer, f));
+               v.push_back(RegionFactory::create (srcs, plist));
+               v.back()->set_whole_file (false);
 
                ++n;
        }
@@ -1090,8 +1028,8 @@ AudioRegion::separate_by_channel (Session& /*session*/, vector<boost::shared_ptr
        return 0;
 }
 
-nframes_t
-AudioRegion::read_raw_internal (Sample* buf, sframes_t pos, nframes_t cnt, int channel) const
+framecnt_t
+AudioRegion::read_raw_internal (Sample* buf, framepos_t pos, framecnt_t cnt, int channel) const
 {
        return audio_source()->read (buf, pos, cnt, channel);
 }
@@ -1177,17 +1115,17 @@ AudioRegion::set_scale_amplitude (gain_t g)
 
        /* tell everybody else */
 
-       send_change (ScaleAmplitudeChanged);
+       send_change (PropertyChange (Properties::scale_amplitude));
 }
 
 void
 AudioRegion::normalize_to (float target_dB)
 {
-       const nframes_t blocksize = 64 * 1024;
+       const framecnt_t blocksize = 64 * 1024;
        Sample buf[blocksize];
-       nframes_t fpos;
-       nframes_t fend;
-       nframes_t to_read;
+       framepos_t fpos;
+       framepos_t fend;
+       framecnt_t to_read;
        double maxamp = 0;
        gain_t target = dB_to_coefficient (target_dB);
 
@@ -1247,31 +1185,31 @@ AudioRegion::normalize_to (float target_dB)
 
        /* tell everybody else */
 
-       send_change (ScaleAmplitudeChanged);
+       send_change (PropertyChange (Properties::scale_amplitude));
 }
 
 void
 AudioRegion::fade_in_changed ()
 {
-       send_change (FadeInChanged);
+       send_change (PropertyChange (Properties::fade_in));
 }
 
 void
 AudioRegion::fade_out_changed ()
 {
-       send_change (FadeOutChanged);
+       send_change (PropertyChange (Properties::fade_out));
 }
 
 void
 AudioRegion::envelope_changed ()
 {
-       send_change (EnvelopeChanged);
+       send_change (PropertyChange (Properties::envelope));
 }
 
 void
 AudioRegion::suspend_fade_in ()
 {
-       if (++_fade_in_disabled == 1) {
+       if (++_fade_in_suspended == 1) {
                if (fade_in_is_default()) {
                        set_fade_in_active (false);
                }
@@ -1281,7 +1219,7 @@ AudioRegion::suspend_fade_in ()
 void
 AudioRegion::resume_fade_in ()
 {
-       if (--_fade_in_disabled == 0 && _fade_in_disabled) {
+       if (--_fade_in_suspended == 0 && _fade_in_suspended) {
                set_fade_in_active (true);
        }
 }
@@ -1289,7 +1227,7 @@ AudioRegion::resume_fade_in ()
 void
 AudioRegion::suspend_fade_out ()
 {
-       if (++_fade_out_disabled == 1) {
+       if (++_fade_out_suspended == 1) {
                if (fade_out_is_default()) {
                        set_fade_out_active (false);
                }
@@ -1299,7 +1237,7 @@ AudioRegion::suspend_fade_out ()
 void
 AudioRegion::resume_fade_out ()
 {
-       if (--_fade_out_disabled == 0 &&_fade_out_disabled) {
+       if (--_fade_out_suspended == 0 &&_fade_out_suspended) {
                set_fade_out_active (true);
        }
 }
@@ -1404,14 +1342,22 @@ AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new)
 
        /* no existing/complete transient info */
 
+        static bool analyse_dialog_shown = false; /* global per instance of Ardour */
+
        if (!Config->get_auto_analyse_audio()) {
-               pl->session().Dialog (_("\
-You have requested an operation that requires audio analysis.\n\n\
+                if (!analyse_dialog_shown) {
+                        pl->session().Dialog (_("\
+You have requested an operation that requires audio analysis.\n\n       \
 You currently have \"auto-analyse-audio\" disabled, which means\n\
 that transient data must be generated every time it is required.\n\n\
 If you are doing work that will require transient data on a\n\
 regular basis, you should probably enable \"auto-analyse-audio\"\n\
-then quit ardour and restart."));
++then quit ardour and restart.\n\n\
++This dialog will not display again.  But you may notice a slight delay\n\
++in this and future transient-detection operations.\n\
++"));
+                        analyse_dialog_shown = true;
+                }
        }
 
        TransientDetector t (pl->session().frame_rate());
@@ -1474,36 +1420,36 @@ then quit ardour and restart."));
  *  @return Silent periods; first of pair is the offset within the region, second is the length of the period
  */
 
-std::list<std::pair<nframes_t, nframes_t> >
-AudioRegion::find_silence (Sample threshold, nframes_t min_length) const
+std::list<std::pair<frameoffset_t, framecnt_t> >
+AudioRegion::find_silence (Sample threshold, framecnt_t min_length, InterThreadInfo& itt) const
 {
-       nframes_t const block_size = 64 * 1024;
+       framecnt_t const block_size = 64 * 1024;
        Sample loudest[block_size];
        Sample buf[block_size];
 
-       nframes_t pos = _start;
-       nframes_t const end = _start + _length - 1;
+       framepos_t pos = _start;
+       framepos_t const end = _start + _length - 1;
 
-       std::list<std::pair<nframes_t, nframes_t> > silent_periods;
+       std::list<std::pair<frameoffset_t, framecnt_t> > silent_periods;
 
        bool in_silence = false;
-       nframes_t silence_start = 0;
+       frameoffset_t silence_start = 0;
        bool silence;
 
-       while (pos < end) {
+       while (pos < end && !itt.cancel) {
 
                /* fill `loudest' with the loudest absolute sample at each instant, across all channels */
                memset (loudest, 0, sizeof (Sample) * block_size);
                for (uint32_t n = 0; n < n_channels(); ++n) {
 
                        read_raw_internal (buf, pos, block_size, n);
-                       for (nframes_t i = 0; i < block_size; ++i) {
+                       for (framecnt_t i = 0; i < block_size; ++i) {
                                loudest[i] = max (loudest[i], abs (buf[i]));
                        }
                }
 
                /* now look for silence */
-               for (nframes_t i = 0; i < block_size; ++i) {
+               for (framecnt_t i = 0; i < block_size; ++i) {
                        silence = abs (loudest[i]) < threshold;
                        if (silence && !in_silence) {
                                /* non-silence to silence */
@@ -1519,6 +1465,7 @@ AudioRegion::find_silence (Sample threshold, nframes_t min_length) const
                }
 
                pos += block_size;
+                itt.progress = (end-pos)/(double)_length;
        }
 
        if (in_silence && end - 1 - silence_start >= min_length) {
@@ -1526,15 +1473,18 @@ AudioRegion::find_silence (Sample threshold, nframes_t min_length) const
                silent_periods.push_back (std::make_pair (silence_start, end));
        }
 
+        itt.done = true;
+
        return silent_periods;
 }
 
 
+
 extern "C" {
 
        int region_read_peaks_from_c (void *arg, uint32_t npeaks, uint32_t start, uint32_t cnt, intptr_t data, uint32_t n_chan, double samples_per_unit)
 {
-       return ((AudioRegion *) arg)->read_peaks ((PeakData *) data, (nframes_t) npeaks, (nframes_t) start, (nframes_t) cnt, n_chan,samples_per_unit);
+       return ((AudioRegion *) arg)->read_peaks ((PeakData *) data, (framecnt_t) npeaks, (framepos_t) start, (framecnt_t) cnt, n_chan,samples_per_unit);
 }
 
 uint32_t region_length_from_c (void *arg)