better design for range plays that leaves the range play button able to play the...
[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::Mutex* Controllable::registry_lock = 0;
35 Controllable::Controllables Controllable::registry;
36
37 Controllable::Controllable (std::string name)
38         : _name (name)
39 {
40         if (registry_lock == 0) {
41                 registry_lock = new Glib::Mutex;
42         }
43
44         add ();
45 }
46
47 Controllable::Controllable (const XMLNode& node)
48 {
49         const XMLProperty* prop = node.property (X_("name"));
50
51         if (!prop) {
52                 fatal << string_compose (_("programming error: %1"), "Controllable (XMLNode&) constructor called without name property")
53                       << endmsg;
54                 /*NOTREACHED*/
55         }
56
57         _name = prop->value ();
58
59         prop = node.property (X_("id"));
60
61         if (!prop) {
62                 fatal << string_compose (_("programming error: %1"), "Controllable (XMLNode&) constructor called without id property")
63                       << endmsg;
64                 /*NOTREACHED*/
65         }
66         
67         _id = prop->value();
68         
69         add ();
70 }
71
72 void
73 Controllable::add ()
74 {
75         Glib::Mutex::Lock lm (*registry_lock);
76         registry.insert (this);
77         this->GoingAway.connect (mem_fun (this, &Controllable::remove));
78 }
79
80 void
81 Controllable::remove ()
82 {
83         Glib::Mutex::Lock lm (*registry_lock);
84         for (Controllables::iterator i = registry.begin(); i != registry.end(); ++i) {
85                 if ((*i) == this) {
86                         registry.erase (i);
87                         break;
88                 }
89         }
90 }
91
92 Controllable*
93 Controllable::by_id (const ID& id)
94 {
95         Glib::Mutex::Lock lm (*registry_lock);
96
97         for (Controllables::iterator i = registry.begin(); i != registry.end(); ++i) {
98                 if ((*i)->id() == id) {
99                         return (*i);
100                 }
101         }
102         return 0;
103 }
104
105
106 Controllable*
107 Controllable::by_name (const std::string& str)
108 {
109         Glib::Mutex::Lock lm (*registry_lock);
110
111         for (Controllables::iterator i = registry.begin(); i != registry.end(); ++i) {
112                 if ((*i)->_name == str) {
113                         return (*i);
114                 }
115         }
116         return 0;
117 }
118
119 XMLNode&
120 Controllable::get_state ()
121 {
122         XMLNode* node = new XMLNode (X_("controllable"));
123         char buf[64];
124
125         node->add_property (X_("name"), _name); // not reloaded from XML state, just there to look at
126         _id.print (buf, sizeof (buf));
127         node->add_property (X_("id"), buf);
128         return *node;
129 }
130
131 int
132 Controllable::set_state (const XMLNode& node)
133 {
134         const XMLProperty* prop = node.property (X_("id"));
135
136         if (prop) {
137                 _id = prop->value();
138                 return 0;
139         } else {
140                 error << _("Controllable state node has no ID property") << endmsg;
141                 return -1;
142         }
143 }