add new sigc++2 directory
[ardour.git] / libs / pbd / stateful.cc
1 /*
2     Copyright (C) 2000-2001 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18     $Id: stateful.cc 629 2006-06-21 23:01:03Z paul $
19 */
20
21 #include <unistd.h>
22
23 #include <pbd/stateful.h>
24 #include <pbd/filesystem.h>
25 #include <pbd/xml++.h>
26 #include <pbd/error.h>
27
28 #include "i18n.h"
29
30 namespace PBD {
31
32 Stateful::Stateful ()
33 {
34         _extra_xml = 0;
35         _instant_xml = 0;
36 }
37
38 Stateful::~Stateful ()
39 {
40         // Do not delete _extra_xml.  The use of add_child_nocopy() 
41         // means it needs to live on indefinately.
42
43         if (_instant_xml) {
44                 delete _instant_xml;
45         }
46 }
47
48 void
49 Stateful::add_extra_xml (XMLNode& node)
50 {
51         if (_extra_xml == 0) {
52                 _extra_xml = new XMLNode ("extra");
53         }
54
55         _extra_xml->remove_nodes (node.name());
56         _extra_xml->add_child_nocopy (node);
57 }
58
59 XMLNode *
60 Stateful::extra_xml (const string& str)
61 {
62         if (_extra_xml == 0) {
63                 return 0;
64         }
65
66         const XMLNodeList& nlist = _extra_xml->children();
67         XMLNodeConstIterator i;
68
69         for (i = nlist.begin(); i != nlist.end(); ++i) {
70                 if ((*i)->name() == str) {
71                         return (*i);
72                 }
73         }
74
75         return 0;
76 }
77
78 void
79 Stateful::add_instant_xml (XMLNode& node, const sys::path& directory_path)
80 {
81         sys::create_directories (directory_path); // may throw
82
83         if (_instant_xml == 0) {
84                 _instant_xml = new XMLNode ("instant");
85         }
86
87         _instant_xml->remove_nodes_and_delete (node.name());
88         _instant_xml->add_child_copy (node);
89
90         sys::path instant_xml_path(directory_path);
91
92         instant_xml_path /= "instant.xml";
93         
94         XMLTree tree;
95         tree.set_filename(instant_xml_path.to_string());
96
97         /* Important: the destructor for an XMLTree deletes
98            all of its nodes, starting at _root. We therefore
99            cannot simply hand it our persistent _instant_xml 
100            node as its _root, because we will lose it whenever
101            the Tree goes out of scope.
102
103            So instead, copy the _instant_xml node (which does 
104            a deep copy), and hand that to the tree.
105         */
106
107         XMLNode* copy = new XMLNode (*_instant_xml);
108         tree.set_root (copy);
109
110         if (!tree.write()) {
111                 error << string_compose(_("Error: could not write %1"), instant_xml_path.to_string()) << endmsg;
112         }
113 }
114
115 XMLNode *
116 Stateful::instant_xml (const string& str, const sys::path& directory_path)
117 {
118         if (_instant_xml == 0) {
119
120                 sys::path instant_xml_path(directory_path);
121                 instant_xml_path /= "instant.xml";
122
123                 if (exists(instant_xml_path)) {
124                         XMLTree tree;
125                         if (tree.read(instant_xml_path.to_string())) {
126                                 _instant_xml = new XMLNode(*(tree.root()));
127                         } else {
128                                 warning << string_compose(_("Could not understand XML file %1"), instant_xml_path.to_string()) << endmsg;
129                                 return 0;
130                         }
131                 } else {
132                         return 0;
133                 }
134         }
135
136         const XMLNodeList& nlist = _instant_xml->children();
137         XMLNodeConstIterator i;
138
139         for (i = nlist.begin(); i != nlist.end(); ++i) {
140                 if ((*i)->name() == str) {
141                         return (*i);
142                 }
143         }
144
145         return 0;
146 }
147
148 } // namespace PBD