(MAY BREAK COMPILATION - unfinished work, being transferred between machines via...
[ardour.git] / libs / pbd / controllable.cc
1 /*
2     Copyright (C) 2000-2007 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 */
19
20 #include "pbd/controllable.h"
21 #include "pbd/xml++.h"
22 #include "pbd/error.h"
23
24 #include "i18n.h"
25
26 using namespace PBD;
27
28 sigc::signal<void,Controllable*> Controllable::Destroyed;
29 sigc::signal<bool,Controllable*> Controllable::StartLearning;
30 sigc::signal<void,Controllable*> Controllable::StopLearning;
31 sigc::signal<void,Controllable*,int,int> Controllable::CreateBinding;
32 sigc::signal<void,Controllable*> Controllable::DeleteBinding;
33
34 Glib::StaticRWLock Controllable::registry_lock = GLIBMM_STATIC_RW_LOCK_INIT;
35 Controllable::Controllables Controllable::registry;
36 Controllable::ControllablesByURI Controllable::registry_by_uri;
37
38 Controllable::Controllable (const std::string& name, const std::string& uri)
39         : _name (name)
40         , _uri (uri)
41         , _touching (false)
42 {
43         add ();
44 }
45
46 void
47 Controllable::add ()
48 {
49         Glib::RWLock::WriterLock lm (*registry_lock);
50         registry.insert (this);
51
52         if (!_uri.empty()) {
53                 pair<string,Controllable*> newpair;
54                 newpair.first = _uri;
55                 newpair.second = this;
56                 registry_by_uri.insert (newpair);
57         }
58
59         this->GoingAway.connect (mem_fun (this, &Controllable::remove));
60 }
61
62 void
63 Controllable::remove ()
64 {
65         Glib::RWLock::WriterLock lm (*registry_lock);
66
67         for (Controllables::iterator i = registry.begin(); i != registry.end(); ++i) {
68                 if ((*i) == this) {
69                         registry.erase (i);
70                         break;
71                 }
72         }
73
74         if (_uri) {
75                 ControllablesByURI::iterator i = registry_by_uri.find (_uri);
76                 if (i != registry_by_uri.end()) {
77                         registry_by_uri.erase (i);
78                 }
79         }
80
81
82 }
83
84 void
85 Controllable::set_uri (const std::string& new_uri)
86 {
87         Glib::RWLock::WriterLock lm (*registry_lock);
88
89         if (_uri) {
90                 ControllablesByURI::iterator i = registry_by_uri.find (_uri);
91                 if (i != registry_by_uri.end()) {
92                         registry_by_uri.erase (i);
93                 }
94         }
95
96         _uri = new_uri;
97
98         if (!_uri.empty()) {
99                 pair<string,Controllable*> newpair;
100                 newpair.first = _uri;
101                 newpair.second = this;
102                 registry_by_uri.insert (newpair);
103         }
104 }
105
106 Controllable*
107 Controllable::by_id (const ID& id)
108 {
109         Glib::RWLock::ReaderLock lm (*registry_lock);
110
111         for (Controllables::iterator i = registry.begin(); i != registry.end(); ++i) {
112                 if ((*i)->id() == id) {
113                         return (*i);
114                 }
115         }
116         return 0;
117 }
118
119 Controllable*
120 Controllable::by_uri (const string& uri)
121 {
122         Glib::RWLock::ReaderLock lm (*registry_lock);
123         ControllablesByURI::iterator i;
124
125         if ((i = registry_by_ui.find (uri)) != registry_by_uri.end()) {
126                 return i->second;
127         }
128         return 0;
129 }
130
131 Controllable*
132 Controllable::by_name (const std::string& str)
133 {
134         Glib::RWLock::ReaderLock lm (*registry_lock);
135
136         for (Controllables::iterator i = registry.begin(); i != registry.end(); ++i) {
137                 if ((*i)->_name == str) {
138                         return (*i);
139                 }
140         }
141         return 0;
142 }
143
144 XMLNode&
145 Controllable::get_state ()
146 {
147         XMLNode* node = new XMLNode (X_("Controllable"));
148         char buf[64];
149
150         node->add_property (X_("name"), _name); // not reloaded from XML state, just there to look at
151         _id.print (buf, sizeof (buf));
152         node->add_property (X_("id"), buf);
153
154         if (!_uri.empty()) {
155                 node->add_property (X_("uri"), _uri);
156         }
157                 
158         return *node;
159 }
160
161 int
162 Controllable::set_state (const XMLNode& node, int /*version*/)
163 {
164         const XMLProperty* prop;
165
166         if ((prop = node.property (X_("id"))) != 0) {
167                 _id = prop->value();
168                 return 0;
169         } else {
170                 error << _("Controllable state node has no ID property") << endmsg;
171                 return -1;
172         }
173
174         if ((prop = node.property (X_("uri"))) != 0) {
175                 set_uri (prop->value());
176         }
177 }