*/
-
-#include "pbd/stacktrace.h"
-
#include "ardour/debug.h"
#include "ardour/types.h"
#include "ardour/crossfade.h"
-#include "ardour/crossfade_compare.h"
#include "ardour/audioregion.h"
#include "ardour/playlist.h"
#include "ardour/utils.h"
#include "ardour/session.h"
#include "ardour/source.h"
+#include "ardour/region_factory.h"
#include "i18n.h"
#include <locale.h>
Crossfade::Crossfade (boost::shared_ptr<AudioRegion> in, boost::shared_ptr<AudioRegion> out,
framecnt_t length,
- framepos_t position,
AnchorPoint ap)
- : AudioRegion (in->session(), position, length, in->name() + string ("<>") + out->name())
+ : AudioRegion (in->session(), 0, length, in->name() + string ("<>") + out->name())
, CROSSFADE_DEFAULT_PROPERTIES
, _fade_in (Evoral::Parameter(FadeInAutomation)) // linear (gain coefficient) => -inf..+6dB
, _fade_out (Evoral::Parameter(FadeOutAutomation)) // linear (gain coefficient) => -inf..+6dB
_out = out;
_anchor_point = ap;
_fixed = true;
+ _follow_overlap = false;
initialize ();
}
initialize ();
}
-Crossfade::Crossfade (const Playlist& playlist, XMLNode& node)
+Crossfade::Crossfade (const Playlist& playlist, XMLNode const & node)
: AudioRegion (playlist.session(), 0, 0, "unnamed crossfade")
, CROSSFADE_DEFAULT_PROPERTIES
, _fade_in (Evoral::Parameter(FadeInAutomation)) // linear (gain coefficient) => -inf..+6dB
{
boost::shared_ptr<Region> r;
- XMLProperty* prop;
+ XMLProperty const * prop;
LocaleGuard lg (X_("POSIX"));
/* we have to find the in/out regions before we can do anything else */
PBD::ID id (prop->value());
- if ((r = playlist.find_region (id)) == 0) {
- error << string_compose (_("Crossfade: no \"in\" region %1 found in playlist %2"), id, playlist.name())
+ r = playlist.find_region (id);
+
+ if (!r) {
+ /* the `in' region is not in a playlist, which probably means that this crossfade
+ is in the undo record, so we have to find the region in the global region map.
+ */
+ r = RegionFactory::region_by_id (id);
+ }
+
+ if (!r) {
+ error << string_compose (_("Crossfade: no \"in\" region %1 found in playlist %2 nor in region map"), id, playlist.name())
<< endmsg;
throw failed_constructor();
}
PBD::ID id2 (prop->value());
- if ((r = playlist.find_region (id2)) == 0) {
- error << string_compose (_("Crossfade: no \"out\" region %1 found in playlist %2"), id2, playlist.name())
+ r = playlist.find_region (id2);
+
+ if (!r) {
+ r = RegionFactory::region_by_id (id2);
+ }
+
+ if (!r) {
+ error << string_compose (_("Crossfade: no \"out\" region %1 found in playlist %2 nor in region map"), id2, playlist.name())
<< endmsg;
throw failed_constructor();
}
}
Crossfade::Crossfade (boost::shared_ptr<Crossfade> orig, boost::shared_ptr<AudioRegion> newin, boost::shared_ptr<AudioRegion> newout)
- : AudioRegion (boost::dynamic_pointer_cast<const AudioRegion> (orig), 0, true)
+ : AudioRegion (boost::dynamic_pointer_cast<const AudioRegion> (orig), 0)
, CROSSFADE_DEFAULT_PROPERTIES
, _fade_in (orig->_fade_in)
, _fade_out (orig->_fade_out)
_sources = _in->sources();
_sources.insert (_sources.end(), _out->sources().begin(), _out->sources().end());
+
+ for (SourceList::iterator i = _sources.begin(); i != _sources.end(); ++i) {
+ (*i)->inc_use_count ();
+ }
+
_master_sources = _in->master_sources();
_master_sources.insert(_master_sources.end(), _out->master_sources().begin(), _out->master_sources().end());
+ for (SourceList::iterator i = _master_sources.begin(); i != _master_sources.end(); ++i) {
+ (*i)->inc_use_count ();
+ }
+
_in_update = false;
_out->suspend_fade_out ();
Sample* mixdown = new Sample[cnt];
float* gain = new float[cnt];
framecnt_t ret;
-
- ret = read_at (buf, mixdown, gain, start, cnt, channel, cnt);
+
+ ret = read_at (buf, mixdown, gain, start, cnt, channel);
delete [] mixdown;
delete [] gain;
framecnt_t
Crossfade::read_at (Sample *buf, Sample *mixdown_buffer,
- float *gain_buffer, framepos_t start, framecnt_t cnt, uint32_t chan_n,
- framecnt_t read_frames, framecnt_t skip_frames) const
+ float *gain_buffer, framepos_t start, framecnt_t cnt, uint32_t chan_n) const
{
frameoffset_t offset;
framecnt_t to_write;
start = _position;
buf += offset;
- to_write = min (_length.val(), (nframes64_t) cnt);
+ to_write = min (_length.val(), cnt);
} else {
memset (crossfade_buffer_in, 0, sizeof (Sample) * to_write);
}
- _out->read_at (crossfade_buffer_out, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
- _in->read_at (crossfade_buffer_in, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
+ _out->read_at (crossfade_buffer_out, mixdown_buffer, gain_buffer, start, to_write, chan_n);
+ _in->read_at (crossfade_buffer_in, mixdown_buffer, gain_buffer, start, to_write, chan_n);
float* fiv = new float[to_write];
float* fov = new float[to_write];
return false;
}
+ /* regions must cannot be identically sized and placed */
+
+ if (_in->position() == _out->position() && _in->length() == _out->length()) {
+ Invalidated (shared_from_this());
+ return false;
+ }
+
/* layer ordering cannot change */
int32_t new_layer_relation = (int32_t) (_in->layer() - _out->layer());
} else {
_position = top->last_frame() - short_xfade_length;
}
-
- _length = min (short_xfade_length, top->length());
+
+ set_xfade_length (min (short_xfade_length, top->length()));
_follow_overlap = false;
_anchor_point = EndOfIn;
_active = true;
_in = top;
_out = bottom;
_position = top->first_frame();
- _length = min (short_xfade_length, top->length());
+ set_xfade_length (min (short_xfade_length, top->length()));
_follow_overlap = false;
_anchor_point = StartOfIn;
_active = true;
if (model == FullCrossfade) {
_position = bottom->first_frame(); // "{"
- _length = _out->first_frame() + _out->length() - _in->first_frame();
+ set_xfade_length (_out->first_frame() + _out->length() - _in->first_frame());
/* leave active alone */
_follow_overlap = true;
} else {
- _length = min (short_xfade_length, top->length());
+ set_xfade_length (min (short_xfade_length, top->length()));
_position = top->last_frame() - _length; // "]" - length
_active = true;
_follow_overlap = false;
_anchor_point = StartOfIn;
if (model == FullCrossfade) {
- _length = _out->first_frame() + _out->length() - _in->first_frame();
+ set_xfade_length (_out->first_frame() + _out->length() - _in->first_frame());
/* leave active alone */
_follow_overlap = true;
} else {
- _length = min (short_xfade_length, top->length());
+ set_xfade_length (min (short_xfade_length, top->length()));
_active = true;
_follow_overlap = false;
char buf[64];
LocaleGuard lg (X_("POSIX"));
+ id().print (buf, sizeof (buf));
+ node->add_property ("id", buf);
_out->id().print (buf, sizeof (buf));
node->add_property ("out", buf);
_in->id().print (buf, sizeof (buf));
PropertyChange what_changed;
framepos_t val;
+ set_id (node);
+
if ((prop = node.property ("position")) != 0) {
sscanf (prop->value().c_str(), "%" PRId64, &val);
if (val != _position) {
}
}
+ if (_fade_in.size() < 2) {
+ /* fade state somehow saved with no points */
+ return -1;
+ }
+
+ _fade_in.front()->value = 0.0;
+ _fade_in.back()->value = 1.0;
+
_fade_in.thaw ();
/* fade out */
}
}
+ if (_fade_out.size() < 2) {
+ /* fade state somehow saved with no points */
+ return -1;
+ }
+
+ _fade_out.front()->value = 1.0;
+ _fade_out.back()->value = 0.0;
+
_fade_out.thaw ();
PropertyChanged (what_changed); /* EMIT SIGNAL */
+ FadesChanged (); /* EMIT SIGNAL */
return 0;
}
_length = len;
PropertyChanged (PropertyChange (Properties::length));
-
+
return len;
}