Invert Pan-Azimuth (up means left)
[ardour.git] / libs / pbd / controllable.cc
1 /*
2  * Copyright (C) 2006-2017 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2009-2011 Carl Hetherington <carl@carlh.net>
4  * Copyright (C) 2009 David Robillard <d@drobilla.net>
5  * Copyright (C) 2016-2019 Robin Gareus <robin@gareus.org>
6  * Copyright (C) 2016 Tim Mayberry <mojofunk@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include "pbd/controllable.h"
24 #include "pbd/enumwriter.h"
25 #include "pbd/xml++.h"
26 #include "pbd/error.h"
27 #include "pbd/types_convert.h"
28 #include "pbd/string_convert.h"
29
30 #include "pbd/i18n.h"
31
32 using namespace PBD;
33 using namespace std;
34
35 PBD::Signal1<bool, boost::weak_ptr<PBD::Controllable> > Controllable::StartLearning;
36 PBD::Signal1<void, boost::weak_ptr<PBD::Controllable> > Controllable::StopLearning;
37 PBD::Signal1<void, boost::weak_ptr<PBD::Controllable> > Controllable::GUIFocusChanged;
38
39 Glib::Threads::RWLock Controllable::registry_lock;
40 Controllable::Controllables Controllable::registry;
41 PBD::ScopedConnectionList Controllable::registry_connections;
42
43 const std::string Controllable::xml_node_name = X_("Controllable");
44
45 Controllable::Controllable (const string& name, Flag f)
46         : _name (name)
47         , _flags (f)
48         , _touching (false)
49 {
50         add (*this);
51 }
52
53 XMLNode&
54 Controllable::get_state ()
55 {
56         XMLNode* node = new XMLNode (xml_node_name);
57
58         /* Waves' "Pressure3" has a parameter called "µ-iness"
59          * which causes a  parser error : Input is not proper UTF-8, indicate encoding !
60          *  Bytes: 0xB5 0x2D 0x69 0x6E
61          *          <Controllable name="�-iness" id="2391" flags="" value="0.000000000000" p
62          */
63
64         // this is not reloaded from XML, but it must be present because it is
65         // used to find and identify XML nodes by various Controllable-derived objects
66
67         node->set_property (X_("name"), _name);
68         node->set_property (X_("id"), id());
69         node->set_property (X_("flags"), _flags);
70         node->set_property (X_("value"), get_save_value());
71
72         if (_extra_xml) {
73                 node->add_child_copy (*_extra_xml);
74         }
75
76         return *node;
77 }
78
79 int
80 Controllable::set_state (const XMLNode& node, int /*version*/)
81 {
82         Stateful::save_extra_xml (node);
83
84         set_id (node);
85
86         if (node.get_property (X_("flags"), _flags)) {
87                 _flags = Flag(_flags | (_flags & Controllable::RealTime));
88         }
89
90         float val;
91         if (node.get_property (X_("value"), val)) {
92                         set_value (val, NoGroup);
93         }
94         return 0;
95 }
96
97 void
98 Controllable::set_flags (Flag f)
99 {
100         _flags = f;
101 }
102
103 void
104 Controllable::add (Controllable& ctl)
105 {
106         Glib::Threads::RWLock::WriterLock lm (registry_lock);
107         registry.insert (&ctl);
108         ctl.DropReferences.connect_same_thread (registry_connections, boost::bind (&Controllable::remove, &ctl));
109         ctl.Destroyed.connect_same_thread (registry_connections, boost::bind (&Controllable::remove, &ctl));
110 }
111
112 void
113 Controllable::remove (Controllable* ctl)
114 {
115         Glib::Threads::RWLock::WriterLock lm (registry_lock);
116         Controllables::iterator i = std::find (registry.begin(), registry.end(), ctl);
117         if (i != registry.end()) {
118                 registry.erase (i);
119         }
120 }
121
122 boost::shared_ptr<Controllable>
123 Controllable::by_id (const ID& id)
124 {
125         Glib::Threads::RWLock::ReaderLock lm (registry_lock);
126
127         for (Controllables::iterator i = registry.begin(); i != registry.end(); ++i) {
128                 if ((*i)->id() == id) {
129                         return (*i)->shared_from_this ();
130                 }
131         }
132         return boost::shared_ptr<Controllable>();
133 }
134
135 void
136 Controllable::dump_registry ()
137 {
138         Glib::Threads::RWLock::ReaderLock lm (registry_lock);
139         if (registry.size() == 0) {
140                 return;
141         }
142         unsigned int cnt = 0;
143         cout << "-- List Of Registered Controllables\n";
144         for (Controllables::iterator i = registry.begin(); i != registry.end(); ++i, ++cnt) {
145                 cout << "CTRL: " << (*i)->name() << "\n";
146         }
147         cout << "Total number of registered sontrollables: " << cnt << "\n";
148 }