More tinkering with State<>. Use some StateDiffCommands instead of

MementoCommand<Region>.  More use of State<> for Region members.


git-svn-id: svn://localhost/ardour2/branches/3.0@6675 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2010-02-11 17:08:34 +00:00
parent 24fbade20a
commit 3a27410dcb
25 changed files with 208 additions and 192 deletions

View file

@ -32,6 +32,7 @@
#include "pbd/pthread_utils.h" #include "pbd/pthread_utils.h"
#include "pbd/memento_command.h" #include "pbd/memento_command.h"
#include "pbd/whitespace.h" #include "pbd/whitespace.h"
#include "pbd/stateful_diff_command.h"
#include <gtkmm2ext/utils.h> #include <gtkmm2ext/utils.h>
#include <gtkmm2ext/choice.h> #include <gtkmm2ext/choice.h>
@ -3177,10 +3178,9 @@ Editor::naturalize ()
begin_reversible_command (_("naturalize")); begin_reversible_command (_("naturalize"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
XMLNode &before = (*i)->region()->get_state(); (*i)->region()->clear_history ();
(*i)->region()->move_to_natural_position (this); (*i)->region()->move_to_natural_position (this);
XMLNode &after = (*i)->region()->get_state(); _session->add_command (new StatefulDiffCommand ((*i)->region().get()));
_session->add_command (new MementoCommand<Region>(*((*i)->region().get()), &before, &after));
} }
commit_reversible_command (); commit_reversible_command ();
} }
@ -4930,10 +4930,9 @@ Editor::toggle_gain_envelope_active ()
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i); AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) { if (arv) {
XMLNode &before = arv->region()->get_state (); arv->region()->clear_history ();
arv->audio_region()->set_envelope_active (!arv->audio_region()->envelope_active()); arv->audio_region()->set_envelope_active (!arv->audio_region()->envelope_active());
XMLNode &after = arv->region()->get_state (); _session->add_command (new StatefulDiffCommand (arv->region().get()));
_session->add_command (new MementoCommand<Region> (*(arv->region().get()), &before, &after));
} }
} }
@ -4952,10 +4951,9 @@ Editor::toggle_region_lock ()
_session->begin_reversible_command (_("region lock")); _session->begin_reversible_command (_("region lock"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
XMLNode &before = (*i)->region()->get_state (); (*i)->region()->clear_history ();
(*i)->region()->set_locked (!(*i)->region()->locked()); (*i)->region()->set_locked (!(*i)->region()->locked());
XMLNode &after = (*i)->region()->get_state (); _session->add_command (new StatefulDiffCommand ((*i)->region().get()));
_session->add_command (new MementoCommand<Region> (*((*i)->region().get()), &before, &after));
} }
_session->commit_reversible_command (); _session->commit_reversible_command ();
@ -4995,10 +4993,9 @@ Editor::toggle_region_mute ()
_session->begin_reversible_command (_("region mute")); _session->begin_reversible_command (_("region mute"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
XMLNode &before = (*i)->region()->get_state (); (*i)->region()->clear_history ();
(*i)->region()->set_muted (!(*i)->region()->muted()); (*i)->region()->set_muted (!(*i)->region()->muted());
XMLNode &after = (*i)->region()->get_state (); _session->add_command (new StatefulDiffCommand ((*i)->region().get()));
_session->add_command (new MementoCommand<Region> (*((*i)->region().get()), &before, &after));
} }
_session->commit_reversible_command (); _session->commit_reversible_command ();
@ -5016,10 +5013,9 @@ Editor::toggle_region_opaque ()
_session->begin_reversible_command (_("region opacity")); _session->begin_reversible_command (_("region opacity"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
XMLNode &before = (*i)->region()->get_state (); (*i)->region()->clear_history ();
(*i)->region()->set_opaque (!(*i)->region()->opaque()); (*i)->region()->set_opaque (!(*i)->region()->opaque());
XMLNode &after = (*i)->region()->get_state (); _session->add_command (new StatefulDiffCommand ((*i)->region().get()));
_session->add_command (new MementoCommand<Region> (*((*i)->region().get()), &before, &after));
} }
_session->commit_reversible_command (); _session->commit_reversible_command ();

View file

@ -2,6 +2,7 @@
#include <gtkmm2ext/utils.h> #include <gtkmm2ext/utils.h>
#include "pbd/memento_command.h" #include "pbd/memento_command.h"
#include "pbd/convert.h"
#include "ardour/transient_detector.h" #include "ardour/transient_detector.h"
#include "ardour/onset_detector.h" #include "ardour/onset_detector.h"

View file

@ -28,6 +28,7 @@
#include <libgnomecanvasmm/item.h> #include <libgnomecanvasmm/item.h>
#include "pbd/error.h" #include "pbd/error.h"
#include "pbd/convert.h"
#include <gtkmm2ext/utils.h> #include <gtkmm2ext/utils.h>
#include <gtkmm2ext/selector.h> #include <gtkmm2ext/selector.h>

View file

@ -70,6 +70,7 @@ namespace ARDOUR {
extern PBD::Change PositionChanged; extern PBD::Change PositionChanged;
extern PBD::Change NameChanged; extern PBD::Change NameChanged;
extern PBD::Change BoundsChanged; extern PBD::Change BoundsChanged;
extern PBD::Change FlagsChanged;
static const double SHUTTLE_FRACT_SPEED1=0.48412291827; /* derived from A1,A2 */ static const double SHUTTLE_FRACT_SPEED1=0.48412291827; /* derived from A1,A2 */

View file

@ -314,21 +314,21 @@ class Region
virtual void recompute_at_end () = 0; virtual void recompute_at_end () = 0;
DataType _type; DataType _type;
Flag _flags; PBD::EnumState<Flag> _flags;
PBD::State<nframes_t> _start; PBD::State<nframes_t> _start;
nframes_t _length; PBD::State<nframes_t> _length;
nframes_t _last_length; nframes_t _last_length;
PBD::State<nframes_t> _position; PBD::State<nframes_t> _position;
nframes_t _last_position; nframes_t _last_position;
PositionLockStyle _positional_lock_style; PositionLockStyle _positional_lock_style;
nframes_t _sync_position; PBD::State<nframes_t> _sync_position;
PBD::State<layer_t> _layer; PBD::State<layer_t> _layer;
mutable RegionEditState _first_edit; mutable RegionEditState _first_edit;
int _frozen; int _frozen;
nframes64_t _ancestral_start; PBD::State<nframes64_t> _ancestral_start;
nframes64_t _ancestral_length; PBD::State<nframes64_t> _ancestral_length;
float _stretch; PBD::State<float> _stretch;
float _shift; PBD::State<float> _shift;
BBT_Time _bbt_time; BBT_Time _bbt_time;
AnalysisFeatureList _transients; AnalysisFeatureList _transients;
bool _valid_transients; bool _valid_transients;

View file

@ -26,6 +26,8 @@
#include "ardour/session_handle.h" #include "ardour/session_handle.h"
#include "i18n.h"
namespace ARDOUR { namespace ARDOUR {
class Session; class Session;
@ -39,11 +41,13 @@ class SessionObject : public SessionHandleRef, public PBD::StatefulDestructible
public: public:
SessionObject (Session& session, const std::string& name) SessionObject (Session& session, const std::string& name)
: SessionHandleRef (session) : SessionHandleRef (session)
, _name(name) , _name (X_("name"), PBD::Change (0), "")
{} {
add_state (_name);
}
Session& session() const { return _session; } Session& session() const { return _session; }
const std::string& name() const { return _name; } std::string name() const { return _name; }
virtual bool set_name (const std::string& str) { virtual bool set_name (const std::string& str) {
if (_name != str) { if (_name != str) {
@ -56,7 +60,7 @@ class SessionObject : public SessionHandleRef, public PBD::StatefulDestructible
PBD::Signal0<void> NameChanged; PBD::Signal0<void> NameChanged;
protected: protected:
std::string _name; PBD::State<std::string> _name;
}; };
} // namespace ARDOUR } // namespace ARDOUR

View file

@ -1433,7 +1433,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
if (s) { if (s) {
srcs.push_back (s); srcs.push_back (s);
s->update_header (capture_info.front()->start, when, twhen); s->update_header (capture_info.front()->start, when, twhen);
s->set_captured_for (_name); s->set_captured_for (_name.get());
s->mark_immutable (); s->mark_immutable ();
if (Config->get_auto_analyse_audio()) { if (Config->get_auto_analyse_audio()) {
Analyser::queue_source_for_analysis (s, true); Analyser::queue_source_for_analysis (s, true);
@ -1970,7 +1970,7 @@ AudioDiskstream::rename_write_sources ()
for (chan = c->begin(), n = 0; chan != c->end(); ++chan, ++n) { for (chan = c->begin(), n = 0; chan != c->end(); ++chan, ++n) {
if ((*chan)->write_source != 0) { if ((*chan)->write_source != 0) {
(*chan)->write_source->set_source_name (_name, destructive()); (*chan)->write_source->set_source_name (_name.get(), destructive());
/* XXX what to do if one of them fails ? */ /* XXX what to do if one of them fails ? */
} }
} }
@ -2178,7 +2178,7 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
first_fs = fs; first_fs = fs;
} }
fs->set_captured_for (_name); fs->set_captured_for (_name.get());
} }
} }

View file

@ -252,7 +252,7 @@ AudioRegionImporter::parse_source_xml ()
return false; return false;
} }
channels = atoi (prop->value()); channels = atoi (prop->value().c_str());
for (uint32_t i = 0; i < channels; ++i) { for (uint32_t i = 0; i < channels; ++i) {
bool source_found = false; bool source_found = false;

View file

@ -305,12 +305,9 @@ void
AudioRegion::set_envelope_active (bool yn) AudioRegion::set_envelope_active (bool yn)
{ {
if (envelope_active() != yn) { if (envelope_active() != yn) {
char buf[64];
if (yn) { if (yn) {
snprintf (buf, sizeof (buf), "envelope active");
_flags = Flag (_flags|EnvelopeActive); _flags = Flag (_flags|EnvelopeActive);
} else { } else {
snprintf (buf, sizeof (buf), "envelope off");
_flags = Flag (_flags & ~EnvelopeActive); _flags = Flag (_flags & ~EnvelopeActive);
} }
send_change (EnvelopeActiveChanged); send_change (EnvelopeActiveChanged);

View file

@ -314,7 +314,7 @@ Crossfade::read_at (Sample *buf, Sample *mixdown_buffer,
start = _position; start = _position;
buf += offset; buf += offset;
to_write = min (_length, cnt); to_write = min (_length.get(), cnt);
} else { } else {
@ -679,7 +679,7 @@ Crossfade::get_state ()
node->add_property ("active", (_active ? "yes" : "no")); node->add_property ("active", (_active ? "yes" : "no"));
node->add_property ("follow-overlap", (_follow_overlap ? "yes" : "no")); node->add_property ("follow-overlap", (_follow_overlap ? "yes" : "no"));
node->add_property ("fixed", (_fixed ? "yes" : "no")); node->add_property ("fixed", (_fixed ? "yes" : "no"));
snprintf (buf, sizeof(buf), "%" PRIu32, _length); snprintf (buf, sizeof(buf), "%" PRIu32, _length.get());
node->add_property ("length", buf); node->add_property ("length", buf);
snprintf (buf, sizeof(buf), "%" PRIu32, (uint32_t) _anchor_point); snprintf (buf, sizeof(buf), "%" PRIu32, (uint32_t) _anchor_point);
node->add_property ("anchor-point", buf); node->add_property ("anchor-point", buf);

View file

@ -396,7 +396,7 @@ Diskstream::playlist_deleted (boost::weak_ptr<Playlist> wpl)
bool bool
Diskstream::set_name (const string& str) Diskstream::set_name (const string& str)
{ {
if (str != _name) { if (_name != str) {
assert(playlist()); assert(playlist());
playlist()->set_name (str); playlist()->set_name (str);

View file

@ -104,6 +104,7 @@ PBD::Change ARDOUR::LengthChanged = PBD::new_change ();
PBD::Change ARDOUR::PositionChanged = PBD::new_change (); PBD::Change ARDOUR::PositionChanged = PBD::new_change ();
PBD::Change ARDOUR::NameChanged = PBD::new_change (); PBD::Change ARDOUR::NameChanged = PBD::new_change ();
PBD::Change ARDOUR::BoundsChanged = Change (0); // see init(), below PBD::Change ARDOUR::BoundsChanged = Change (0); // see init(), below
PBD::Change ARDOUR::FlagsChanged = PBD::new_change ();
compute_peak_t ARDOUR::compute_peak = 0; compute_peak_t ARDOUR::compute_peak = 0;
find_peaks_t ARDOUR::find_peaks = 0; find_peaks_t ARDOUR::find_peaks = 0;

View file

@ -1086,7 +1086,7 @@ IO::set_name (const string& requested_name)
{ {
string name = requested_name; string name = requested_name;
if (name == _name) { if (_name == name) {
return true; return true;
} }
@ -1098,7 +1098,7 @@ IO::set_name (const string& requested_name)
for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) { for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
string current_name = i->name(); string current_name = i->name();
current_name.replace (current_name.find (_name), _name.length(), name); current_name.replace (current_name.find (_name), _name.get().length(), name);
i->set_name (current_name); i->set_name (current_name);
} }
@ -1267,7 +1267,7 @@ IO::build_legal_port_name (DataType type)
char buf1[name_size+1]; char buf1[name_size+1];
char buf2[name_size+1]; char buf2[name_size+1];
snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str()); snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.get().c_str(), suffix.c_str());
int port_number = find_port_hole (buf1); int port_number = find_port_hole (buf1);
snprintf (buf2, name_size+1, "%s %d", buf1, port_number); snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
@ -1342,9 +1342,9 @@ IO::setup_bundle ()
_bundle->remove_channels (); _bundle->remove_channels ();
if (_direction == Input) { if (_direction == Input) {
snprintf(buf, sizeof (buf), _("%s in"), _name.c_str()); snprintf(buf, sizeof (buf), _("%s in"), _name.get().c_str());
} else { } else {
snprintf(buf, sizeof (buf), _("%s out"), _name.c_str()); snprintf(buf, sizeof (buf), _("%s out"), _name.get().c_str());
} }
_bundle->set_name (buf); _bundle->set_name (buf);
uint32_t const ni = _ports.num_ports(); uint32_t const ni = _ports.num_ports();

View file

@ -170,7 +170,7 @@ IOProcessor::set_state (const XMLNode& node, int version)
for (niter = nlist.begin(); niter != nlist.end(); ++niter) { for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
const XMLProperty* prop; const XMLProperty* prop;
if ((prop = (*niter)->property ("name")) != 0) { if ((prop = (*niter)->property ("name")) != 0) {
if (prop->value() == _name) { if (_name == prop->value()) {
if ((prop = (*niter)->property ("direction")) != 0) { if ((prop = (*niter)->property ("direction")) != 0) {
if (prop->value() == instr) { if (prop->value() == instr) {
io_node = (*niter); io_node = (*niter);
@ -200,7 +200,7 @@ IOProcessor::set_state (const XMLNode& node, int version)
if ((*niter)->name() == "IO") { if ((*niter)->name() == "IO") {
const XMLProperty* prop; const XMLProperty* prop;
if ((prop = (*niter)->property ("name")) != 0) { if ((prop = (*niter)->property ("name")) != 0) {
if (prop->value() == _name) { if (_name == prop->value()) {
if ((prop = (*niter)->property ("direction")) != 0) { if ((prop = (*niter)->property ("direction")) != 0) {
if (prop->value() == outstr) { if (prop->value() == outstr) {
io_node = (*niter); io_node = (*niter);

View file

@ -1388,7 +1388,7 @@ int
MidiDiskstream::rename_write_sources () MidiDiskstream::rename_write_sources ()
{ {
if (_write_source != 0) { if (_write_source != 0) {
_write_source->set_source_name (_name, destructive()); _write_source->set_source_name (_name.get(), destructive());
/* XXX what to do if this fails ? */ /* XXX what to do if this fails ? */
} }
return 0; return 0;

View file

@ -51,7 +51,7 @@ using namespace PBD;
MidiRegion::MidiRegion (boost::shared_ptr<MidiSource> src, nframes_t start, nframes_t length) MidiRegion::MidiRegion (boost::shared_ptr<MidiSource> src, nframes_t start, nframes_t length)
: Region (src, start, length, PBD::basename_nosuffix(src->name()), DataType::MIDI, 0, Region::Flag(Region::DefaultFlags|Region::External)) : Region (src, start, length, PBD::basename_nosuffix(src->name()), DataType::MIDI, 0, Region::Flag(Region::DefaultFlags|Region::External))
{ {
assert(_name.find("/") == string::npos); assert(_name.get().find("/") == string::npos);
midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1)); midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1));
} }
@ -59,7 +59,7 @@ MidiRegion::MidiRegion (boost::shared_ptr<MidiSource> src, nframes_t start, nfra
MidiRegion::MidiRegion (boost::shared_ptr<MidiSource> src, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags) MidiRegion::MidiRegion (boost::shared_ptr<MidiSource> src, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags)
: Region (src, start, length, name, DataType::MIDI, layer, flags) : Region (src, start, length, name, DataType::MIDI, layer, flags)
{ {
assert(_name.find("/") == string::npos); assert(_name.get().find("/") == string::npos);
midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1)); midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1));
} }
@ -67,7 +67,7 @@ MidiRegion::MidiRegion (boost::shared_ptr<MidiSource> src, nframes_t start, nfra
MidiRegion::MidiRegion (const SourceList& srcs, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags) MidiRegion::MidiRegion (const SourceList& srcs, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags)
: Region (srcs, start, length, name, DataType::MIDI, layer, flags) : Region (srcs, start, length, name, DataType::MIDI, layer, flags)
{ {
assert(_name.find("/") == string::npos); assert(_name.get().find("/") == string::npos);
midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1)); midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1));
} }
@ -76,14 +76,14 @@ MidiRegion::MidiRegion (const SourceList& srcs, nframes_t start, nframes_t lengt
MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other, nframes_t offset, nframes_t length, const string& name, layer_t layer, Flag flags) MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other, nframes_t offset, nframes_t length, const string& name, layer_t layer, Flag flags)
: Region (other, offset, length, name, layer, flags) : Region (other, offset, length, name, layer, flags)
{ {
assert(_name.find("/") == string::npos); assert(_name.get().find("/") == string::npos);
midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1)); midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1));
} }
MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other) MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other)
: Region (other) : Region (other)
{ {
assert(_name.find("/") == string::npos); assert(_name.get().find("/") == string::npos);
midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1)); midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1));
} }
@ -95,7 +95,7 @@ MidiRegion::MidiRegion (boost::shared_ptr<MidiSource> src, const XMLNode& node)
} }
midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1)); midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1));
assert(_name.find("/") == string::npos); assert(_name.get().find("/") == string::npos);
assert(_type == DataType::MIDI); assert(_type == DataType::MIDI);
} }
@ -107,7 +107,7 @@ MidiRegion::MidiRegion (const SourceList& srcs, const XMLNode& node)
} }
midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1)); midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1));
assert(_name.find("/") == string::npos); assert(_name.get().find("/") == string::npos);
assert(_type == DataType::MIDI); assert(_type == DataType::MIDI);
} }

View file

@ -230,7 +230,7 @@ MidiSource::session_saved()
if (_model && _model->edited()) { if (_model && _model->edited()) {
string newname; string newname;
const string basename = PBD::basename_nosuffix(_name); const string basename = PBD::basename_nosuffix(_name.get());
string::size_type last_dash = basename.find_last_of("-"); string::size_type last_dash = basename.find_last_of("-");
if (last_dash == string::npos || last_dash == basename.find_first_of("-")) { if (last_dash == string::npos || last_dash == basename.find_first_of("-")) {
newname = basename + "-1"; newname = basename + "-1";

View file

@ -19,6 +19,7 @@
#include "pbd/error.h" #include "pbd/error.h"
#include "pbd/enumwriter.h" #include "pbd/enumwriter.h"
#include "pbd/convert.h"
#include "midi++/events.h" #include "midi++/events.h"
#include "evoral/midi_util.h" #include "evoral/midi_util.h"

View file

@ -60,29 +60,36 @@ void
Region::register_states () Region::register_states ()
{ {
_xml_node_name = X_("Region"); _xml_node_name = X_("Region");
add_state (_flags);
add_state (_start); add_state (_start);
add_state (_length);
add_state (_position); add_state (_position);
add_state (_sync_position);
add_state (_layer); add_state (_layer);
add_state (_ancestral_start);
add_state (_ancestral_length);
add_state (_stretch);
add_state (_shift);
} }
/* derived-from-derived constructor (no sources in constructor) */ /* derived-from-derived constructor (no sources in constructor) */
Region::Region (Session& s, nframes_t start, nframes_t length, const string& name, DataType type, layer_t layer, Region::Flag flags) Region::Region (Session& s, nframes_t start, nframes_t length, const string& name, DataType type, layer_t layer, Region::Flag flags)
: SessionObject(s, name) : SessionObject(s, name)
, _type(type) , _type(type)
, _flags(Flag (flags|DoNotSendPropertyChanges)) , _flags (X_("flags"), FlagsChanged, Flag (flags|DoNotSendPropertyChanges))
, _start (X_("start"), StartChanged, start) , _start (X_("start"), StartChanged, start)
, _length(length) , _length (X_("length"), LengthChanged, length)
, _position (X_("position"), PositionChanged, 0) , _position (X_("position"), PositionChanged, 0)
, _last_position(0) , _last_position (0)
, _positional_lock_style(AudioTime) , _positional_lock_style(AudioTime)
, _sync_position(_start) , _sync_position (X_("sync-position"), SyncOffsetChanged, _start)
, _layer (X_("layer"), LayerChanged, layer) , _layer (X_("layer"), LayerChanged, layer)
, _first_edit(EditChangesNothing) , _first_edit(EditChangesNothing)
, _frozen(0) , _frozen(0)
, _ancestral_start (0) , _ancestral_start (X_("ancestral-start"), Change (0), 0)
, _ancestral_length (0) , _ancestral_length (X_("ancestral-length"), Change (0), 0)
, _stretch(1.0) , _stretch (X_("stretch"), Change (0), 1.0)
, _shift(1.0) , _shift (X_("shift"), Change (0), 1.0)
, _read_data_count(0) , _read_data_count(0)
, _pending_changed(Change (0)) , _pending_changed(Change (0))
, _last_layer_op(0) , _last_layer_op(0)
@ -97,20 +104,20 @@ Region::Region (Session& s, nframes_t start, nframes_t length, const string& nam
Region::Region (boost::shared_ptr<Source> src, nframes_t start, nframes_t length, const string& name, DataType type, layer_t layer, Region::Flag flags) Region::Region (boost::shared_ptr<Source> src, nframes_t start, nframes_t length, const string& name, DataType type, layer_t layer, Region::Flag flags)
: SessionObject(src->session(), name) : SessionObject(src->session(), name)
, _type(type) , _type(type)
, _flags(Flag (flags|DoNotSendPropertyChanges)) , _flags (X_("flags"), FlagsChanged, Flag (flags|DoNotSendPropertyChanges))
, _start (X_("start"), StartChanged, start) , _start (X_("start"), StartChanged, start)
, _length(length) , _length (X_("length"), LengthChanged, length)
, _position (X_("position"), PositionChanged, 0) , _position (X_("position"), PositionChanged, 0)
, _last_position(0) , _last_position(0)
, _positional_lock_style(AudioTime) , _positional_lock_style(AudioTime)
, _sync_position(_start) , _sync_position (X_("sync-position"), SyncOffsetChanged, _start)
, _layer (X_("layer"), LayerChanged, layer) , _layer (X_("layer"), LayerChanged, layer)
, _first_edit(EditChangesNothing) , _first_edit(EditChangesNothing)
, _frozen(0) , _frozen(0)
, _ancestral_start (0) , _ancestral_start (X_("ancestral-start"), Change (0), 0)
, _ancestral_length (0) , _ancestral_length (X_("ancestral-length"), Change (0), 0)
, _stretch (1.0) , _stretch (X_("stretch"), Change (0), 1.0)
, _shift (1.0) , _shift (X_("shift"), Change (0), 1.0)
, _valid_transients(false) , _valid_transients(false)
, _read_data_count(0) , _read_data_count(0)
, _pending_changed(Change (0)) , _pending_changed(Change (0))
@ -132,20 +139,20 @@ Region::Region (boost::shared_ptr<Source> src, nframes_t start, nframes_t length
Region::Region (const SourceList& srcs, nframes_t start, nframes_t length, const string& name, DataType type, layer_t layer, Region::Flag flags) Region::Region (const SourceList& srcs, nframes_t start, nframes_t length, const string& name, DataType type, layer_t layer, Region::Flag flags)
: SessionObject(srcs.front()->session(), name) : SessionObject(srcs.front()->session(), name)
, _type(type) , _type(type)
, _flags(Flag (flags|DoNotSendPropertyChanges)) , _flags (X_("flags"), FlagsChanged, Flag (flags|DoNotSendPropertyChanges))
, _start (X_("start"), StartChanged, start) , _start (X_("start"), StartChanged, start)
, _length(length) , _length (X_("length"), LengthChanged, length)
, _position (X_("position"), PositionChanged, 0) , _position (X_("position"), PositionChanged, 0)
, _last_position(0) , _last_position(0)
, _positional_lock_style(AudioTime) , _positional_lock_style(AudioTime)
, _sync_position(_start) , _sync_position (X_("sync-position"), SyncOffsetChanged, _start)
, _layer (X_("layer"), LayerChanged, layer) , _layer (X_("layer"), LayerChanged, layer)
, _first_edit(EditChangesNothing) , _first_edit(EditChangesNothing)
, _frozen(0) , _frozen(0)
, _ancestral_start (0) , _ancestral_start (X_("ancestral-start"), Change (0), 0)
, _ancestral_length (0) , _ancestral_length (X_("ancestral-length"), Change (0), 0)
, _stretch(1.0) , _stretch (X_("stretch"), Change (0), 1.0)
, _shift(1.0) , _shift (X_("shift"), Change (0), 1.0)
, _read_data_count(0) , _read_data_count(0)
, _pending_changed(Change (0)) , _pending_changed(Change (0))
, _last_layer_op(0) , _last_layer_op(0)
@ -161,9 +168,16 @@ Region::Region (const SourceList& srcs, nframes_t start, nframes_t length, const
Region::Region (boost::shared_ptr<const Region> other, nframes_t offset, nframes_t length, const string& name, layer_t layer, Flag flags) Region::Region (boost::shared_ptr<const Region> other, nframes_t offset, nframes_t length, const string& name, layer_t layer, Flag flags)
: SessionObject(other->session(), name) : SessionObject(other->session(), name)
, _type (other->data_type()) , _type (other->data_type())
, _flags (X_("flags"), FlagsChanged, Flag (flags | DoNotSendPropertyChanges))
, _start (X_("start"), StartChanged, 0) , _start (X_("start"), StartChanged, 0)
, _length (X_("length"), LengthChanged, 0)
, _position (X_("position"), PositionChanged, 0) , _position (X_("position"), PositionChanged, 0)
, _sync_position (X_("sync-position"), SyncOffsetChanged, 0)
, _layer (X_("layer"), LayerChanged, 0) , _layer (X_("layer"), LayerChanged, 0)
, _ancestral_start (X_("ancestral-start"), Change (0), 0)
, _ancestral_length (X_("ancestral-length"), Change (0), 0)
, _stretch (X_("stretch"), Change (0), 1.0)
, _shift (X_("shift"), Change (0), 1.0)
, _pending_explicit_relayer (false) , _pending_explicit_relayer (false)
{ {
@ -172,8 +186,6 @@ Region::Region (boost::shared_ptr<const Region> other, nframes_t offset, nframes
_start = other->_start + offset; _start = other->_start + offset;
copy_stuff (other, offset, length, name, layer, flags); copy_stuff (other, offset, length, name, layer, flags);
_flags = Flag (_flags | DoNotSendPropertyChanges);
/* if the other region had a distinct sync point /* if the other region had a distinct sync point
set, then continue to use it as best we can. set, then continue to use it as best we can.
otherwise, reset sync point back to start. otherwise, reset sync point back to start.
@ -206,9 +218,16 @@ Region::Region (boost::shared_ptr<const Region> other, nframes_t offset, nframes
Region::Region (boost::shared_ptr<const Region> other, nframes_t length, const string& name, layer_t layer, Flag flags) Region::Region (boost::shared_ptr<const Region> other, nframes_t length, const string& name, layer_t layer, Flag flags)
: SessionObject(other->session(), name) : SessionObject(other->session(), name)
, _type (other->data_type()) , _type (other->data_type())
, _flags (X_("flags"), FlagsChanged, Flag (flags|DoNotSendPropertyChanges))
, _start (X_("start"), StartChanged, 0) , _start (X_("start"), StartChanged, 0)
, _length (X_("length"), LengthChanged, 0)
, _position (X_("position"), PositionChanged, 0) , _position (X_("position"), PositionChanged, 0)
, _sync_position (X_("sync-position"), SyncOffsetChanged, 0)
, _layer (X_("layer"), LayerChanged, 0) , _layer (X_("layer"), LayerChanged, 0)
, _ancestral_start (X_("ancestral-start"), Change (0), 0)
, _ancestral_length (X_("ancestral-length"), Change (0), 0)
, _stretch (X_("stretch"), Change (0), 1.0)
, _shift (X_("shift"), Change (0), 1.0)
, _pending_explicit_relayer (false) , _pending_explicit_relayer (false)
{ {
register_states (); register_states ();
@ -266,7 +285,7 @@ Region::Region (boost::shared_ptr<const Region> other, nframes_t length, const s
Region::Region (boost::shared_ptr<const Region> other) Region::Region (boost::shared_ptr<const Region> other)
: SessionObject(other->session(), other->name()) : SessionObject(other->session(), other->name())
, _type(other->data_type()) , _type(other->data_type())
, _flags(Flag(other->_flags & ~(Locked|PositionLocked))) , _flags (other->_flags)
, _start(other->_start) , _start(other->_start)
, _length(other->_length) , _length(other->_length)
, _position(other->_position) , _position(other->_position)
@ -288,6 +307,7 @@ Region::Region (boost::shared_ptr<const Region> other)
{ {
register_states (); register_states ();
_flags = Flag (_flags & ~ (Locked | PositionLocked));
_flags = Flag (_flags | DoNotSendPropertyChanges); _flags = Flag (_flags | DoNotSendPropertyChanges);
other->_first_edit = EditChangesName; other->_first_edit = EditChangesName;
@ -305,18 +325,20 @@ Region::Region (boost::shared_ptr<const Region> other)
Region::Region (const SourceList& srcs, const XMLNode& node) Region::Region (const SourceList& srcs, const XMLNode& node)
: SessionObject(srcs.front()->session(), X_("error: XML did not reset this")) : SessionObject(srcs.front()->session(), X_("error: XML did not reset this"))
, _type(DataType::NIL) // to be loaded from XML , _type(DataType::NIL) // to be loaded from XML
, _flags(DoNotSendPropertyChanges) , _flags (X_("flags"), FlagsChanged, Flag (DoNotSendPropertyChanges))
, _start (X_("start"), StartChanged, 0) , _start (X_("start"), StartChanged, 0)
, _length(0) , _length (X_("length"), LengthChanged, 0)
, _position (X_("position"), PositionChanged, 0) , _position (X_("position"), PositionChanged, 0)
, _last_position(0) , _last_position(0)
, _positional_lock_style(AudioTime) , _positional_lock_style(AudioTime)
, _sync_position(_start) , _sync_position (X_("sync-position"), SyncOffsetChanged, _start)
, _layer (X_("layer"), LayerChanged, 0) , _layer (X_("layer"), LayerChanged, 0)
, _first_edit(EditChangesNothing) , _first_edit(EditChangesNothing)
, _frozen(0) , _frozen(0)
, _stretch(1.0) , _ancestral_start (X_("ancestral-start"), Change (0), 0)
, _shift(1.0) , _ancestral_length (X_("ancestral-length"), Change (0), 0)
, _stretch (X_("stretch"), Change (0), 1.0)
, _shift (X_("shift"), Change (0), 1.0)
, _read_data_count(0) , _read_data_count(0)
, _pending_changed(Change(0)) , _pending_changed(Change(0))
, _last_layer_op(0) , _last_layer_op(0)
@ -337,18 +359,20 @@ Region::Region (const SourceList& srcs, const XMLNode& node)
Region::Region (boost::shared_ptr<Source> src, const XMLNode& node) Region::Region (boost::shared_ptr<Source> src, const XMLNode& node)
: SessionObject(src->session(), X_("error: XML did not reset this")) : SessionObject(src->session(), X_("error: XML did not reset this"))
, _type(DataType::NIL) , _type(DataType::NIL)
, _flags(DoNotSendPropertyChanges) , _flags (X_("flags"), FlagsChanged, Flag (DoNotSendPropertyChanges))
, _start (X_("start"), StartChanged, 0) , _start (X_("start"), StartChanged, 0)
, _length(0) , _length (X_("length"), LengthChanged, 0)
, _position (X_("position"), PositionChanged, 0) , _position (X_("position"), PositionChanged, 0)
, _last_position(0) , _last_position(0)
, _positional_lock_style(AudioTime) , _positional_lock_style(AudioTime)
, _sync_position(_start) , _sync_position (X_("sync-position"), SyncOffsetChanged, _start)
, _layer (X_("layer"), LayerChanged, 0) , _layer (X_("layer"), LayerChanged, 0)
, _first_edit(EditChangesNothing) , _first_edit(EditChangesNothing)
, _frozen(0) , _frozen(0)
, _stretch(1.0) , _ancestral_start (X_("ancestral-start"), Change (0), 0)
, _shift(1.0) , _ancestral_length (X_("ancestral-length"), Change (0), 0)
, _stretch (X_("stretch"), Change (0), 1.0)
, _shift (X_("shift"), Change (0), 1.0)
, _read_data_count(0) , _read_data_count(0)
, _pending_changed(Change(0)) , _pending_changed(Change(0))
, _last_layer_op(0) , _last_layer_op(0)
@ -1096,18 +1120,7 @@ Region::state (bool /*full_state*/)
_id.print (buf, sizeof (buf)); _id.print (buf, sizeof (buf));
node->add_property ("id", buf); node->add_property ("id", buf);
node->add_property ("name", _name);
node->add_property ("type", _type.to_string()); node->add_property ("type", _type.to_string());
snprintf (buf, sizeof (buf), "%u", _length);
node->add_property ("length", buf);
snprintf (buf, sizeof (buf), "%" PRIi64, _ancestral_start);
node->add_property ("ancestral-start", buf);
snprintf (buf, sizeof (buf), "%" PRIi64, _ancestral_length);
node->add_property ("ancestral-length", buf);
snprintf (buf, sizeof (buf), "%.12g", _stretch);
node->add_property ("stretch", buf);
snprintf (buf, sizeof (buf), "%.12g", _shift);
node->add_property ("shift", buf);
switch (_first_edit) { switch (_first_edit) {
case EditChangesNothing: case EditChangesNothing:
@ -1128,9 +1141,6 @@ Region::state (bool /*full_state*/)
/* note: flags are stored by derived classes */ /* note: flags are stored by derived classes */
snprintf (buf, sizeof (buf), "%" PRIu32, _sync_position);
node->add_property ("sync-position", buf);
if (_positional_lock_style != AudioTime) { if (_positional_lock_style != AudioTime) {
node->add_property ("positional-lock-style", enum_2_string (_positional_lock_style)); node->add_property ("positional-lock-style", enum_2_string (_positional_lock_style));
stringstream str; stringstream str;
@ -1152,41 +1162,17 @@ Region::set_live_state (const XMLNode& node, int /*version*/, Change& what_chang
{ {
const XMLNodeList& nlist = node.children(); const XMLNodeList& nlist = node.children();
const XMLProperty *prop; const XMLProperty *prop;
nframes_t val;
/* this is responsible for setting those aspects of Region state /* this is responsible for setting those aspects of Region state
that are mutable after construction. that are mutable after construction.
*/ */
if ((prop = node.property ("name"))) {
_name = prop->value();
}
if ((prop = node.property ("type")) == 0) { if ((prop = node.property ("type")) == 0) {
_type = DataType::AUDIO; _type = DataType::AUDIO;
} else { } else {
_type = DataType(prop->value()); _type = DataType(prop->value());
} }
if ((prop = node.property ("length")) != 0) {
sscanf (prop->value().c_str(), "%" PRIu32, &val);
if (val != _length) {
what_changed = Change (what_changed|LengthChanged);
cerr << _name << " length changed\n";
_last_length = _length;
_length = val;
}
}
if ((prop = node.property ("sync-position")) != 0) {
sscanf (prop->value().c_str(), "%" PRIu32, &val);
if (val != _sync_position) {
what_changed = Change (what_changed|SyncOffsetChanged);
cerr << _name << " sync changed\n";
_sync_position = val;
}
}
if ((prop = node.property ("positional-lock-style")) != 0) { if ((prop = node.property ("positional-lock-style")) != 0) {
_positional_lock_style = PositionLockStyle (string_2_enum (prop->value(), _positional_lock_style)); _positional_lock_style = PositionLockStyle (string_2_enum (prop->value(), _positional_lock_style));
@ -1208,47 +1194,17 @@ Region::set_live_state (const XMLNode& node, int /*version*/, Change& what_chang
/* XXX FIRST EDIT !!! */ /* XXX FIRST EDIT !!! */
/* these 3 properties never change as a result of any editing */ /* fix problems with old sessions corrupted by impossible
values for _stretch or _shift
if ((prop = node.property ("ancestral-start")) != 0) { */
_ancestral_start = strtoll (prop->value().c_str(), 0, 10); if (_stretch == 0.0) {
} else {
_ancestral_start = _start;
}
if ((prop = node.property ("ancestral-length")) != 0) {
_ancestral_length = strtoll (prop->value().c_str(), 0, 10);
} else {
_ancestral_length = _length;
}
if ((prop = node.property ("stretch")) != 0) {
_stretch = atof (prop->value());
/* fix problem with old sessions corrupted by an impossible
value for _stretch
*/
if (_stretch == 0.0) {
_stretch = 1.0;
}
} else {
_stretch = 1.0; _stretch = 1.0;
} }
if ((prop = node.property ("shift")) != 0) { if (_shift == 0.0) {
_shift = atof (prop->value());
/* fix problem with old sessions corrupted by an impossible
value for _shift
*/
if (_shift == 0.0) {
_shift = 1.0;
}
} else {
_shift = 1.0; _shift = 1.0;
} }
/* note: derived classes set flags */ /* note: derived classes set flags */
for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) { for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {

View file

@ -26,6 +26,7 @@
#include "pbd/enumwriter.h" #include "pbd/enumwriter.h"
#include "pbd/memento_command.h" #include "pbd/memento_command.h"
#include "pbd/stacktrace.h" #include "pbd/stacktrace.h"
#include "pbd/convert.h"
#include "evoral/Curve.hpp" #include "evoral/Curve.hpp"

View file

@ -41,6 +41,7 @@
#include "pbd/basename.h" #include "pbd/basename.h"
#include "pbd/stacktrace.h" #include "pbd/stacktrace.h"
#include "pbd/file_utils.h" #include "pbd/file_utils.h"
#include "pbd/convert.h"
#include "ardour/amp.h" #include "ardour/amp.h"
#include "ardour/analyser.h" #include "ardour/analyser.h"

View file

@ -64,6 +64,7 @@
#include "pbd/pthread_utils.h" #include "pbd/pthread_utils.h"
#include "pbd/search_path.h" #include "pbd/search_path.h"
#include "pbd/stacktrace.h" #include "pbd/stacktrace.h"
#include "pbd/convert.h"
#include "ardour/amp.h" #include "ardour/amp.h"
#include "ardour/audio_diskstream.h" #include "ardour/audio_diskstream.h"

View file

@ -306,7 +306,7 @@ SndFileSource::read_unlocked (Sample *dst, sframes_t start, nframes_t cnt) const
if (sf_seek (sf, (sf_count_t) start, SEEK_SET|SFM_READ) != (sf_count_t) start) { if (sf_seek (sf, (sf_count_t) start, SEEK_SET|SFM_READ) != (sf_count_t) start) {
char errbuf[256]; char errbuf[256];
sf_error_str (0, errbuf, sizeof (errbuf) - 1); sf_error_str (0, errbuf, sizeof (errbuf) - 1);
error << string_compose(_("SndFileSource: could not seek to frame %1 within %2 (%3)"), start, _name.substr (1), errbuf) << endmsg; error << string_compose(_("SndFileSource: could not seek to frame %1 within %2 (%3)"), start, _name.get().substr (1), errbuf) << endmsg;
return 0; return 0;
} }
@ -316,7 +316,7 @@ SndFileSource::read_unlocked (Sample *dst, sframes_t start, nframes_t cnt) const
if (ret != file_cnt) { if (ret != file_cnt) {
char errbuf[256]; char errbuf[256];
sf_error_str (0, errbuf, sizeof (errbuf) - 1); sf_error_str (0, errbuf, sizeof (errbuf) - 1);
cerr << string_compose(_("SndFileSource: @ %1 could not read %2 within %3 (%4) (len = %5)"), start, file_cnt, _name.substr (1), errbuf, _length) << endl; cerr << string_compose(_("SndFileSource: @ %1 could not read %2 within %3 (%4) (len = %5)"), start, file_cnt, _name.get().substr (1), errbuf, _length) << endl;
} }
return ret; return ret;
} }

View file

@ -7,5 +7,6 @@
#define _(Text) dgettext (PACKAGE, Text) #define _(Text) dgettext (PACKAGE, Text)
#define N_(Text) gettext_noop (Text) #define N_(Text) gettext_noop (Text)
#define X_(Text) (Text) #define X_(Text) (Text)
#define I18N(Array) PBD::internationalize (PACKAGE, Array)
#endif // __i18n_h__ #endif // __i18n_h__

View file

@ -24,6 +24,7 @@
#include <cassert> #include <cassert>
#include "pbd/id.h" #include "pbd/id.h"
#include "pbd/xml++.h" #include "pbd/xml++.h"
#include "pbd/enumwriter.h"
class XMLNode; class XMLNode;
@ -51,14 +52,6 @@ public:
} }
StateBase (StateBase const & s)
: _have_old (s._have_old)
, _xml_property_name (s._xml_property_name)
, _change (s._change)
{
}
/** Forget about any old value for this state */ /** Forget about any old value for this state */
void clear_history () { void clear_history () {
_have_old = false; _have_old = false;
@ -74,26 +67,19 @@ protected:
Change _change; Change _change;
}; };
/** Class to represent a single piece of state in a Stateful object */ /** Parent class for classes which represent a single piece of state in a Stateful object */
template <class T> template <class T>
class State : public StateBase class StateTemplate : public StateBase
{ {
public: public:
State (std::string const & p, Change c, T const & v) StateTemplate (std::string const & p, Change c, T const & v)
: StateBase (p, c) : StateBase (p, c)
, _current (v) , _current (v)
{ {
} }
State (State<T> const & s) StateTemplate<T> & operator= (StateTemplate<T> const & s) {
: StateBase (s)
{
_current = s._current;
_old = s._old;
}
State<T> & operator= (State<T> const & s) {
/* XXX: isn't there a nicer place to do this? */ /* XXX: isn't there a nicer place to do this? */
_have_old = s._have_old; _have_old = s._have_old;
_xml_property_name = s._xml_property_name; _xml_property_name = s._xml_property_name;
@ -114,7 +100,15 @@ public:
return _current; return _current;
} }
operator T () const { bool operator== (std::string const & o) const {
return o == to_string (_current);
}
bool operator!= (std::string const & o) const {
return o != to_string (_current);
}
operator T const & () const {
return _current; return _current;
} }
@ -137,9 +131,7 @@ public:
XMLProperty const * p = node.property (_xml_property_name.c_str()); XMLProperty const * p = node.property (_xml_property_name.c_str());
if (p) { if (p) {
std::stringstream s (p->value ()); T const v = from_string (p->value ());
T v;
s >> v;
if (v == _current) { if (v == _current) {
return Change (0); return Change (0);
@ -156,21 +148,83 @@ public:
node.add_property (_xml_property_name.c_str(), to_string (_current)); node.add_property (_xml_property_name.c_str(), to_string (_current));
} }
private: protected:
void set (T const & v) { void set (T const & v) {
_old = _current; _old = _current;
_have_old = true; _have_old = true;
_current = v; _current = v;
} }
virtual std::string to_string (T const & v) const = 0;
virtual T from_string (std::string const & s) const = 0;
T _current;
T _old;
};
template<class T>
std::ostream& operator<< (std::ostream& os, StateTemplate<T> const & s)
{
os << s.get();
return os;
}
/** Representation of a single piece of state in a Stateful; for use
* with types that can be written to / read from stringstreams.
*/
template <class T>
class State : public StateTemplate<T>
{
public:
State (std::string const & p, Change c, T const & v)
: StateTemplate<T> (p, c, v)
{
}
T & operator= (T const & v) {
this->set (v);
return this->_current;
}
private:
std::string to_string (T const & v) const { std::string to_string (T const & v) const {
std::stringstream s; std::stringstream s;
s << v; s << v;
return s.str (); return s.str ();
} }
T _current; T from_string (std::string const & s) const {
T _old; std::stringstream t (s);
T v;
t >> v;
return v;
}
};
template <class T>
class EnumState : public StateTemplate<T>
{
public:
EnumState (std::string const & p, Change c, T const & v)
: StateTemplate<T> (p, c, v)
{
}
T & operator= (T const & v) {
this->set (v);
return this->_current;
}
private:
std::string to_string (T const & v) const {
return enum_2_string (v);
}
T from_string (std::string const & v) const {
return T (string_2_enum (v, this->_current));
}
}; };
/** Base class for objects with saveable and undoable state */ /** Base class for objects with saveable and undoable state */