#include <cstdlib>
-
#include "ardour/types.h"
+#include "ardour/debug.h"
#include "ardour/configuration.h"
#include "ardour/audioplaylist.h"
#include "ardour/audioregion.h"
using namespace std;
using namespace PBD;
+namespace ARDOUR {
+ namespace Properties {
+ PBD::PropertyDescriptor<bool> crossfades;
+ }
+}
+
+void
+AudioPlaylist::make_property_quarks ()
+{
+ Properties::crossfades.property_id = g_quark_from_static_string (X_("crossfades"));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for crossfades = %1\n", Properties::crossfades.property_id));
+}
+
+CrossfadeListProperty::CrossfadeListProperty (AudioPlaylist& pl)
+ : SequenceProperty<std::list<boost::shared_ptr<Crossfade> > > (Properties::crossfades.property_id, boost::bind (&AudioPlaylist::update, &pl, _1))
+ , _playlist (pl)
+{
+
+}
+
+CrossfadeListProperty::CrossfadeListProperty (CrossfadeListProperty const & p)
+ : PBD::SequenceProperty<std::list<boost::shared_ptr<Crossfade> > > (p)
+ , _playlist (p._playlist)
+{
+
+}
+
+
+CrossfadeListProperty *
+CrossfadeListProperty::create () const
+{
+ return new CrossfadeListProperty (_playlist);
+}
+
+CrossfadeListProperty *
+CrossfadeListProperty::clone () const
+{
+ return new CrossfadeListProperty (*this);
+}
+
+void
+CrossfadeListProperty::get_content_as_xml (boost::shared_ptr<Crossfade> xfade, XMLNode & node) const
+{
+ /* Crossfades are not written to any state when they are no
+ longer in use, so we must write their state here.
+ */
+
+ XMLNode& c = xfade->get_state ();
+ node.add_child_nocopy (c);
+}
+
+boost::shared_ptr<Crossfade>
+CrossfadeListProperty::get_content_from_xml (XMLNode const & node) const
+{
+ XMLNodeList const c = node.children ();
+ assert (c.size() == 1);
+ return boost::shared_ptr<Crossfade> (new Crossfade (_playlist, *c.front()));
+}
+
+
AudioPlaylist::AudioPlaylist (Session& session, const XMLNode& node, bool hidden)
: Playlist (session, node, DataType::AUDIO, hidden)
+ , _crossfades (*this)
{
+#ifndef NDEBUG
const XMLProperty* prop = node.property("type");
assert(!prop || DataType(prop->value()) == DataType::AUDIO);
+#endif
+
+ add_property (_crossfades);
in_set_state++;
set_state (node, Stateful::loading_state_version);
AudioPlaylist::AudioPlaylist (Session& session, string name, bool hidden)
: Playlist (session, name, DataType::AUDIO, hidden)
+ , _crossfades (*this)
{
+ add_property (_crossfades);
}
AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, string name, bool hidden)
: Playlist (other, name, hidden)
+ , _crossfades (*this)
{
+ add_property (_crossfades);
+
RegionList::const_iterator in_o = other->regions.begin();
RegionList::iterator in_n = regions.begin();
AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, nframes_t start, nframes_t cnt, string name, bool hidden)
: Playlist (other, start, cnt, name, hidden)
+ , _crossfades (*this)
{
+ add_property (_crossfades);
+
/* this constructor does NOT notify others (session) */
}
AudioPlaylist::~AudioPlaylist ()
{
- drop_references ();
-
- /* drop connections to signals */
-
_crossfades.clear ();
}
if ((*i)->coverage (start, end) != OverlapNone) {
relevant_regions[(*i)->layer()].push_back (*i);
relevant_layers.push_back ((*i)->layer());
- }
+ }
}
for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
vector<boost::shared_ptr<Region> > r (relevant_regions[*l]);
vector<boost::shared_ptr<Crossfade> >& x (relevant_xfades[*l]);
+
for (vector<boost::shared_ptr<Region> >::iterator i = r.begin(); i != r.end(); ++i) {
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*i);
+ DEBUG_TRACE (DEBUG::AudioPlayback, string_compose ("read from region %1\n", ar->name()));
assert(ar);
ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames);
_read_data_count += ar->read_data_count();
void
-AudioPlaylist::flush_notifications ()
+AudioPlaylist::flush_notifications (bool from_undo)
{
- Playlist::flush_notifications();
+ Playlist::flush_notifications (from_undo);
if (in_flush) {
return;
}
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
-
- nframes_t xfade_length;
-
other = boost::dynamic_pointer_cast<AudioRegion> (*i);
if (other == region) {
touched_regions = 0;
try {
+ framecnt_t xfade_length;
switch (c) {
case OverlapNone:
break;
audio engineering.
*/
- xfade_length = min ((nframes_t) 720, top->length());
+ xfade_length = min ((framecnt_t) 720, top->length());
if (top_region_at (top->first_frame()) == top) {
} else {
touched_regions = regions_touched (top->first_frame(),
- top->first_frame() + min ((nframes_t)_session.config.get_short_xfade_seconds() * _session.frame_rate(),
+ top->first_frame() + min ((framecnt_t) _session.config.get_short_xfade_seconds() * _session.frame_rate(),
top->length()));
if (touched_regions->size() <= 2) {
xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, _session.config.get_xfade_model(), _session.config.get_xfades_active()));
} else {
touched_regions = regions_touched (bottom->first_frame(),
- bottom->first_frame() + min ((nframes_t)_session.config.get_short_xfade_seconds() * _session.frame_rate(),
+ bottom->first_frame() + min ((framecnt_t)_session.config.get_short_xfade_seconds() * _session.frame_rate(),
bottom->length()));
if (touched_regions->size() <= 2) {
xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, _session.config.get_xfade_model(), _session.config.get_xfades_active()));
_crossfades.push_back (xfade);
xfade->Invalidated.connect_same_thread (*this, boost::bind (&AudioPlaylist::crossfade_invalidated, this, _1));
- xfade->StateChanged.connect_same_thread (*this, boost::bind (&AudioPlaylist::crossfade_changed, this, _1));
+ xfade->PropertyChanged.connect_same_thread (*this, boost::bind (&AudioPlaylist::crossfade_changed, this, _1));
notify_crossfade_added (xfade);
}
boost::shared_ptr<Crossfade> xfade = boost::shared_ptr<Crossfade> (new Crossfade (*((const Playlist *)this), *child));
_crossfades.push_back (xfade);
xfade->Invalidated.connect_same_thread (*this, boost::bind (&AudioPlaylist::crossfade_invalidated, this, _1));
- xfade->StateChanged.connect_same_thread (*this, boost::bind (&AudioPlaylist::crossfade_changed, this, _1));
+ xfade->PropertyChanged.connect_same_thread (*this, boost::bind (&AudioPlaylist::crossfade_changed, this, _1));
NewCrossfade(xfade);
}
AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
{
boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
+
+ if (!r) {
+ return false;
+ }
+
bool changed = false;
Crossfades::iterator c, ctmp;
set<boost::shared_ptr<Crossfade> > unique_xfades;
- if (r == 0) {
- fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
- << endmsg;
- /*NOTREACHED*/
- return false;
- }
-
{
RegionLock rlock (this);
}
void
-AudioPlaylist::crossfade_changed (Change)
+AudioPlaylist::crossfade_changed (const PropertyChange&)
{
if (in_flush || in_set_state) {
return;
that occured.
*/
- notify_modified ();
+ notify_contents_changed ();
}
bool
-AudioPlaylist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
+AudioPlaylist::region_changed (const PropertyChange& what_changed, boost::shared_ptr<Region> region)
{
if (in_flush || in_set_state) {
return false;
}
- Change our_interests = Change (AudioRegion::FadeInChanged|
- AudioRegion::FadeOutChanged|
- AudioRegion::FadeInActiveChanged|
- AudioRegion::FadeOutActiveChanged|
- AudioRegion::EnvelopeActiveChanged|
- AudioRegion::ScaleAmplitudeChanged|
- AudioRegion::EnvelopeChanged);
+ PropertyChange our_interests;
+
+ our_interests.add (Properties::fade_in_active);
+ our_interests.add (Properties::fade_out_active);
+ our_interests.add (Properties::scale_amplitude);
+ our_interests.add (Properties::envelope_active);
+ our_interests.add (Properties::envelope);
+ our_interests.add (Properties::fade_in);
+ our_interests.add (Properties::fade_out);
+
bool parent_wants_notify;
parent_wants_notify = Playlist::region_changed (what_changed, region);
- if ((parent_wants_notify || (what_changed & our_interests))) {
- notify_modified ();
+ if (parent_wants_notify || (what_changed.contains (our_interests))) {
+ notify_contents_changed ();
}
return true;
s (*i);
}
}
+
+void
+AudioPlaylist::update (const CrossfadeListProperty::ChangeRecord& change)
+{
+ for (CrossfadeListProperty::ChangeContainer::const_iterator i = change.added.begin(); i != change.added.end(); ++i) {
+ add_crossfade (*i);
+ }
+
+ /* don't remove crossfades here; they will be dealt with by the dependency code */
+}