root/branches/libffado-2.0/src/libcontrol/Element.cpp

Revision 1385, 7.3 kB (checked in by ppalmers, 12 years ago)

Implement a mechanism to disable the samplerate and clock source controls while the device is streaming in order to avoid changes that could mess up jack. The saffire pro controls that cause a device reset to
happen are also disabled while streaming is active.

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 Util::Mutex&
95 Element::getLock()
96 {
97     assert(m_parent != NULL || m_element_lock != NULL);
98     if(m_parent) {
99         return m_parent->getLock();
100     } else {
101         return *m_element_lock;
102     }
103 }
104
105 bool
106 Element::canChangeValue()
107 {
108     return true;
109 }
110
111 void
112 Element::show()
113 {
114     debugOutput( DEBUG_LEVEL_NORMAL, "Element %s\n",
115         getName().c_str());
116 }
117
118 void
119 Element::setVerboseLevel(int l)
120 {
121     setDebugLevel(l);
122     if(m_element_lock) m_element_lock->setVerboseLevel(l);
123     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
124 }
125
126 bool
127 Element::addSignalHandler( SignalFunctor* functor )
128 {
129     debugOutput(DEBUG_LEVEL_VERBOSE, "Adding signal handler (%p)\n", functor);
130     m_signalHandlers.push_back( functor );
131     return true;
132 }
133
134 bool
135 Element::remSignalHandler( SignalFunctor* functor )
136 {
137     debugOutput(DEBUG_LEVEL_VERBOSE, "Removing signal handler (%p)\n", functor);
138
139     for ( std::vector< SignalFunctor* >::iterator it = m_signalHandlers.begin();
140           it != m_signalHandlers.end();
141           ++it )
142     {
143         if ( *it == functor ) {
144             debugOutput(DEBUG_LEVEL_VERBOSE, " found\n");
145             m_signalHandlers.erase( it );
146             return true;
147         }
148     }
149     debugOutput(DEBUG_LEVEL_VERBOSE, " not found\n");
150     return false;
151 }
152
153 bool
154 Element::emitSignal(int id, int value)
155 {
156     for ( std::vector< SignalFunctor* >::iterator it = m_signalHandlers.begin();
157           it != m_signalHandlers.end();
158           ++it )
159     {
160         SignalFunctor *f = *it;
161         if(f && f->m_id == id) (*f)(value);
162     }
163     return true;
164 }
165
166 bool
167 Element::emitSignal(int id)
168 {
169     for ( std::vector< SignalFunctor* >::iterator it = m_signalHandlers.begin();
170           it != m_signalHandlers.end();
171           ++it )
172     {
173         SignalFunctor *f = *it;
174         if(f && f->m_id == id) (*f)();
175     }
176     return true;
177 }
178
179 //// --- Container --- ////
180 Container::Container(Element *p)
181 : Element(p)
182 {
183 }
184
185 Container::Container(Element *p, std::string n)
186 : Element(p, n)
187 {
188 }
189
190 Container::~Container()
191 {
192 }
193
194 unsigned int
195 Container::countElements()
196 {
197     lockControl();
198     unsigned int s = m_Children.size();
199     unlockControl();
200     return s;
201 }
202
203 const ElementVector &
204 Container::getElementVector()
205 {
206     if(!getLock().isLocked()) {
207         debugWarning("called on unlocked tree!\n");
208     }
209     return m_Children;
210 }
211
212 bool
213 Container::addElement(Element *e)
214 {
215     Util::MutexLockHelper lock(getLock());
216     if (e==NULL) {
217         debugWarning("Cannot add NULL element\n");
218         return false;
219     }
220
221     debugOutput( DEBUG_LEVEL_VERBOSE, "Adding Element %s to %s\n",
222         e->getName().c_str(), getName().c_str());
223
224     // don't allow duplicates, only makes life hard
225     for ( ElementVectorIterator it = m_Children.begin();
226       it != m_Children.end();
227       ++it )
228     {
229         if(*it == e) {
230             debugOutput( DEBUG_LEVEL_VERBOSE, "Not adding Element %s, already present\n",
231                 e->getName().c_str());
232             return false;
233         }
234     }
235
236     m_Children.push_back(e);
237     // unlock before emitting the signal
238     lock.earlyUnlock();
239     emitSignal(eS_Updated, m_Children.size());
240     return true;
241 }
242
243 bool
244 Container::deleteElementNoLock(Element *e)
245 {
246     if(e == NULL) return false;
247     debugOutput( DEBUG_LEVEL_VERBOSE, "Deleting Element %s from %s\n",
248         e->getName().c_str(), getName().c_str());
249
250     for ( ElementVectorIterator it = m_Children.begin();
251       it != m_Children.end();
252       ++it )
253     {
254         if(*it == e) {
255             m_Children.erase(it);
256             return true;
257         }
258     }
259
260     debugOutput( DEBUG_LEVEL_VERBOSE, "Element %s not found \n",e->getName().c_str());
261     return false; //not found
262 }
263
264 bool
265 Container::deleteElement(Element *e)
266 {
267     bool retval;
268     Util::MutexLockHelper lock(getLock());
269     retval = deleteElementNoLock(e);
270     if(retval) {
271         // unlock before emitting the signal
272         lock.earlyUnlock();
273         emitSignal(eS_Updated, m_Children.size());
274     }
275     return retval;
276 }
277
278 bool
279 Container::clearElements(bool delete_pointers)
280 {
281     Util::MutexLockHelper lock(getLock());
282     while(m_Children.size()) {
283         Element *e=m_Children[0];
284         deleteElementNoLock(e);
285         if (delete_pointers) delete e;
286     }
287
288     // unlock before emitting the signal
289     lock.earlyUnlock();
290     emitSignal(eS_Updated, m_Children.size());
291     return true;
292 }
293
294 void
295 Container::show()
296 {
297     Util::MutexLockHelper lock(getLock());
298     debugOutput( DEBUG_LEVEL_NORMAL, "Container %s (%d Elements)\n",
299         getName().c_str(), m_Children.size());
300
301     for ( ElementVectorIterator it = m_Children.begin();
302       it != m_Children.end();
303       ++it )
304     {
305         (*it)->show();
306     }
307 }
308
309 void
310 Container::setVerboseLevel(int l)
311 {
312     setDebugLevel(l);
313     for ( ElementVectorIterator it = m_Children.begin();
314       it != m_Children.end();
315       ++it )
316     {
317         (*it)->setVerboseLevel(l);
318     }
319     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
320 }
321
322 } // namespace Control
Note: See TracBrowser for help on using the browser.