MSVC project changes needed to support the new 'mp3 import' stuff
[ardour.git] / libs / pbd / stateful_diff_command.cc
1 /*
2  * Copyright (C) 2010-2016 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2010 Carl Hetherington <carl@carlh.net>
4  * Copyright (C) 2012-2016 Tim Mayberry <mojofunk@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include "pbd/stateful_diff_command.h"
22 #include "pbd/types_convert.h"
23 #include "pbd/property_list.h"
24 #include "pbd/demangle.h"
25 #include "pbd/i18n.h"
26
27 using namespace std;
28 using namespace PBD;
29
30 /** Create a new StatefulDiffCommand by examining the changes made to a Stateful
31  *  since the last time that clear_changes was called on it.
32  *  @param s Stateful object.
33  */
34
35 StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<StatefulDestructible> s)
36         : _object (s)
37         , _changes (0)
38 {
39         _changes = s->get_changes_as_properties (this);
40
41         /* if the stateful object that this command refers to goes away,
42            be sure to notify owners of this command.
43         */
44
45         s->DropReferences.connect_same_thread (*this, boost::bind (&Destructible::drop_references, this));
46 }
47
48 StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<StatefulDestructible> s, XMLNode const & n)
49         : _object (s)
50         , _changes (0)
51 {
52         const XMLNodeList& children (n.children());
53
54         for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
55                 if ((*i)->name() == X_("Changes")) {
56                         _changes = s->property_factory (**i);
57                 }
58         }
59
60         assert (_changes != 0);
61
62         /* if the stateful object that this command refers to goes away,
63            be sure to notify owners of this command.
64         */
65
66         s->DropReferences.connect_same_thread (*this, boost::bind (&Destructible::drop_references, this));
67 }
68
69 StatefulDiffCommand::~StatefulDiffCommand ()
70 {
71         drop_references ();
72
73         delete _changes;
74 }
75
76 void
77 StatefulDiffCommand::operator() ()
78 {
79         boost::shared_ptr<Stateful> s (_object.lock());
80
81         if (s) {
82                 s->apply_changes (*_changes);
83         }
84 }
85
86 void
87 StatefulDiffCommand::undo ()
88 {
89         boost::shared_ptr<Stateful> s (_object.lock());
90
91         if (s) {
92                 PropertyList p = *_changes;
93                 p.invert ();
94                 s->apply_changes (p);
95         }
96 }
97
98 XMLNode&
99 StatefulDiffCommand::get_state ()
100 {
101         boost::shared_ptr<Stateful> s (_object.lock());
102
103         if (!s) {
104                 /* XXX should we throw? */
105                 return * new XMLNode("");
106         }
107
108         XMLNode* node = new XMLNode (X_("StatefulDiffCommand"));
109
110         node->set_property ("obj-id", s->id());
111         node->set_property ("type-name", demangled_name (*s.get()));
112
113         XMLNode* changes = new XMLNode (X_("Changes"));
114
115         _changes->get_changes_as_xml (changes);
116
117         node->add_child_nocopy (*changes);
118
119         return *node;
120 }
121
122 bool
123 StatefulDiffCommand::empty () const
124 {
125         return _changes->empty();
126 }