root/trunk/libffado/src/libcontrol/Element.cpp

Revision 2802, 8.1 kB (checked in by jwoithe, 3 years ago)

Cosmetic: "Firewire" becomes "FireWire?".

Officially both the "F" and "W" were capitalised in the FireWire? name, so
reflect this throughout FFADO's source tree. This mostly affects comments.

This patch originated from pander on the ffado-devel mailing list. To
maintain consistency, the committed version has been expanded to include
files not originally included in the original patch.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free FireWire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "Element.h"
25
26 #include "libutil/PosixMutex.h"
27
28 namespace Control {
29
30 IMPL_DEBUG_MODULE( Element, Element, DEBUG_LEVEL_NORMAL );
31
32 // This serves as an ID
33 // incremented on every Element creation
34 // ID's are unique as long as we don't create
35 // more than 2^64 elements.
36 // if we would create 1000 Elements per second
37 // we'd still need >500000 years to wrap.
38 // I guess we're safe.
39 static uint64_t GlobalElementCounter=0;
40
41 Element::Element(Element *parent)
42 : m_element_lock ( NULL )
43 , m_parent( parent )
44 , m_Name ( "NoName" )
45 , m_Label ( "No Label" )
46 , m_Description ( "No Description" )
47 , m_id(GlobalElementCounter++)
48 {
49     // no parent, we are the root of an independent control tree
50     // this means we have to create a lock
51     if(parent == NULL) {
52         m_element_lock = new Util::PosixMutex("CTLEL");
53     }
54 }
55
56 Element::Element(Element *parent, std::string n)
57 : m_element_lock ( NULL )
58 , m_parent( parent )
59 , m_Name( n )
60 , m_Label ( "No Label" )
61 , m_Description ( "No Description" )
62 , m_id(GlobalElementCounter++)
63 {
64     // no parent, we are the root of an independent control tree
65     // this means we have to create a lock
66     if(parent == NULL) {
67         m_element_lock = new Util::PosixMutex("CTLEL");
68     }
69 }
70
71 Element::~Element()
72 {
73     if(m_element_lock) delete m_element_lock;
74 }
75
76 void
77 Element::lockControl()
78 {
79     if(!m_parent) {
80         debugOutput( DEBUG_LEVEL_VERBOSE, "Locking tree...\n");
81     }
82     getLock().Lock();
83 }
84
85 void
86 Element::unlockControl()
87 {
88     if(!m_parent) {
89         debugOutput( DEBUG_LEVEL_VERBOSE, "Unlocking tree...\n");
90     }
91     getLock().Unlock();
92 }
93
94 bool
95 Element::isControlLocked()
96 {
97     return getLock().isLocked();
98 }
99
100 Util::Mutex&
101 Element::getLock()
102 {
103     assert(m_parent != NULL || m_element_lock != NULL);
104     if(m_parent) {
105         return m_parent->getLock();
106     } else {
107         return *m_element_lock;
108     }
109 }
110
111 bool
112 Element::canChangeValue()
113 {
114     return true;
115 }
116
117 void
118 Element::show()
119 {
120     debugOutput( DEBUG_LEVEL_NORMAL, "Element %s\n",
121         getName().c_str());
122 }
123
124 void
125 Element::setVerboseLevel(int l)
126 {
127     setDebugLevel(l);
128     if(m_element_lock) m_element_lock->setVerboseLevel(l);
129     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
130 }
131
132 bool
133 Element::addSignalHandler( SignalFunctor* functor )
134 {
135     debugOutput(DEBUG_LEVEL_VERBOSE, "Adding signal handler (%p)\n", functor);
136     m_signalHandlers.push_back( functor );
137     return true;
138 }
139
140 bool
141 Element::remSignalHandler( SignalFunctor* functor )
142 {
143     debugOutput(DEBUG_LEVEL_VERBOSE, "Removing signal handler (%p)\n", functor);
144
145     for ( std::vector< SignalFunctor* >::iterator it = m_signalHandlers.begin();
146           it != m_signalHandlers.end();
147           ++it )
148     {
149         if ( *it == functor ) {
150             debugOutput(DEBUG_LEVEL_VERBOSE, " found\n");
151             m_signalHandlers.erase( it );
152             return true;
153         }
154     }
155     debugOutput(DEBUG_LEVEL_VERBOSE, " not found\n");
156     return false;
157 }
158
159 bool
160 Element::emitSignal(int id, int value)
161 {
162     for ( std::vector< SignalFunctor* >::iterator it = m_signalHandlers.begin();
163           it != m_signalHandlers.end();
164           ++it )
165     {
166         SignalFunctor *f = *it;
167         if(f && f->m_id == id) (*f)(value);
168     }
169     return true;
170 }
171
172 bool
173 Element::emitSignal(int id)
174 {
175     for ( std::vector< SignalFunctor* >::iterator it = m_signalHandlers.begin();
176           it != m_signalHandlers.end();
177           ++it )
178     {
179         SignalFunctor *f = *it;
180         if(f && f->m_id == id) (*f)();
181     }
182     return true;
183 }
184
185 //// --- Container --- ////
186 Container::Container(Element *p)
187 : Element(p)
188 {
189 }
190
191 Container::Container(Element *p, std::string n)
192 : Element(p, n)
193 {
194 }
195
196 Container::~Container()
197 {
198 }
199
200 unsigned int
201 Container::countElements()
202 {
203     lockControl();
204     unsigned int s = m_Children.size();
205     unlockControl();
206     return s;
207 }
208
209 const ElementVector &
210 Container::getElementVector()
211 {
212     if(!getLock().isLocked()) {
213         debugWarning("called on unlocked tree!\n");
214     }
215     return m_Children;
216 }
217
218 /**
219  * Finds an element by name
220  * Note that you have to run this with the lock held,
221  * otherwise there is no guarantee that the element will
222  * not be deleted from the tree by an async event (e.g. busreset)
223  *
224  * @param name element name
225  * @return element or null if not found
226  */
227 Element *
228 Container::getElementByName(std::string name) {
229     if(!getLock().isLocked()) debugWarning("Getting a Config::Element without locking the control tree, dangerous!\n");
230     for ( ElementVectorIterator it = m_Children.begin();
231       it != m_Children.end();
232       ++it )
233     {
234         if((*it)->getName() == name) {
235             debugOutput( DEBUG_LEVEL_VERBOSE, "Found Element %s (%s) \n",
236                 (*it)->getName().c_str(), (*it)->getDescription().c_str());
237             return *it;
238         }
239     }
240     return NULL;
241 }
242
243 bool
244 Container::addElement(Element *e)
245 {
246     Util::MutexLockHelper lock(getLock());
247     if (e==NULL) {
248         debugWarning("Cannot add NULL element\n");
249         return false;
250     }
251
252     debugOutput( DEBUG_LEVEL_VERBOSE, "Adding Element %s to %s\n",
253         e->getName().c_str(), getName().c_str());
254
255     // don't allow duplicates, only makes life hard
256     for ( ElementVectorIterator it = m_Children.begin();
257       it != m_Children.end();
258       ++it )
259     {
260         if(*it == e) {
261             debugOutput( DEBUG_LEVEL_VERBOSE, "Not adding Element %s, already present\n",
262                 e->getName().c_str());
263             return false;
264         }
265     }
266
267     m_Children.push_back(e);
268     // unlock before emitting the signal
269     lock.earlyUnlock();
270     emitSignal(eS_Updated, m_Children.size());
271     return true;
272 }
273
274 bool
275 Container::deleteElementNoLock(Element *e)
276 {
277     if(e == NULL) return false;
278     debugOutput( DEBUG_LEVEL_VERBOSE, "Deleting Element %s from %s\n",
279         e->getName().c_str(), getName().c_str());
280
281     for ( ElementVectorIterator it = m_Children.begin();
282       it != m_Children.end();
283       ++it )
284     {
285         if(*it == e) {
286             m_Children.erase(it);
287             return true;
288         }
289     }
290
291     debugOutput( DEBUG_LEVEL_VERBOSE, "Element %s not found \n",e->getName().c_str());
292     return false; //not found
293 }
294
295 bool
296 Container::deleteElement(Element *e)
297 {
298     bool retval;
299     Util::MutexLockHelper lock(getLock());
300     retval = deleteElementNoLock(e);
301     if(retval) {
302         // unlock before emitting the signal
303         lock.earlyUnlock();
304         emitSignal(eS_Updated, m_Children.size());
305     }
306     return retval;
307 }
308
309 bool
310 Container::clearElements(bool delete_pointers)
311 {
312     Util::MutexLockHelper lock(getLock());
313     while(m_Children.size()) {
314         Element *e=m_Children[0];
315         deleteElementNoLock(e);
316         if (delete_pointers) delete e;
317     }
318
319     // unlock before emitting the signal
320     lock.earlyUnlock();
321     emitSignal(eS_Updated, m_Children.size());
322     return true;
323 }
324
325 void
326 Container::show()
327 {
328     Util::MutexLockHelper lock(getLock());
329     debugOutput( DEBUG_LEVEL_NORMAL, "Container %s (%zd Elements)\n",
330         getName().c_str(), m_Children.size());
331
332     for ( ElementVectorIterator it = m_Children.begin();
333       it != m_Children.end();
334       ++it )
335     {
336         (*it)->show();
337     }
338 }
339
340 void
341 Container::setVerboseLevel(int l)
342 {
343     setDebugLevel(l);
344     for ( ElementVectorIterator it = m_Children.begin();
345       it != m_Children.end();
346       ++it )
347     {
348         (*it)->setVerboseLevel(l);
349     }
350     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
351 }
352
353 } // namespace Control
Note: See TracBrowser for help on using the browser.