Changeset 1163
- Timestamp:
- 05/11/08 15:04:25 (15 years ago)
- Files:
-
- trunk/libffado/src/devicemanager.cpp (modified) (16 diffs)
- trunk/libffado/src/devicemanager.h (modified) (4 diffs)
- trunk/libffado/src/libcontrol/Element.cpp (modified) (4 diffs)
- trunk/libffado/src/libcontrol/Element.h (modified) (5 diffs)
- trunk/libffado/src/libieee1394/ieee1394service.cpp (modified) (1 diff)
- trunk/libffado/src/libutil/Mutex.h (modified) (1 diff)
- trunk/libffado/support/dbus/control-interface.xml (modified) (1 diff)
- trunk/libffado/support/dbus/controlserver.cpp (modified) (23 diffs)
- trunk/libffado/support/dbus/controlserver.h (modified) (13 diffs)
- trunk/libffado/support/dbus/ffado-dbus-server.cpp (modified) (4 diffs)
- trunk/libffado/support/dbus/test-dbus-server.cpp (modified) (1 diff)
- trunk/libffado/support/mixer/ffadomixer.in (modified) (2 diffs)
- trunk/libffado/tests/test-ffado.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/libffado/src/devicemanager.cpp
r1158 r1163 37 37 #include "debugmodule/debugmodule.h" 38 38 39 #include "libutil/PosixMutex.h" 40 39 41 #ifdef ENABLE_BEBOB 40 42 #include "bebob/bebob_avdevice.h" … … 82 84 DeviceManager::DeviceManager() 83 85 : Control::Container(NULL, "devicemanager") // this is the control root node 86 , m_avDevicesLock( new Util::PosixMutex() ) 87 , m_BusResetLock( new Util::PosixMutex() ) 84 88 , m_processorManager( new Streaming::StreamProcessorManager() ) 85 89 , m_deviceStringParser( new DeviceStringParser() ) … … 95 99 DeviceManager::~DeviceManager() 96 100 { 101 m_avDevicesLock->Lock(); // make sure nobody is using this 97 102 for ( FFADODeviceVectorIterator it = m_avDevices.begin(); 98 103 it != m_avDevices.end(); … … 104 109 delete *it; 105 110 } 106 107 // the SP's are automatically unregistered at the SPM 111 m_avDevicesLock->Unlock(); 112 delete m_avDevicesLock; 113 114 // the SP's are automatically unregistered from the SPM 108 115 delete m_processorManager; 109 116 … … 114 121 delete *it; 115 122 } 123 delete m_BusResetLock; 116 124 117 125 for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin(); … … 214 222 DeviceManager::busresetHandler() 215 223 { 224 // serialize bus reset handling since it can be that a new one occurs while we're 225 // doing stuff. 226 Util::MutexLockHelper lock(*m_BusResetLock); 216 227 debugOutput( DEBUG_LEVEL_VERBOSE, "Bus reset...\n" ); 217 228 if(m_ignore_busreset) { … … 221 232 222 233 // FIXME: what port was the bus reset on? 234 // FIXME: what if the devices are gone? 223 235 // propagate the bus reset to all avDevices 236 m_avDevicesLock->Lock(); // make sure nobody is using this 224 237 for ( FFADODeviceVectorIterator it = m_avDevices.begin(); 225 238 it != m_avDevices.end(); … … 228 241 (*it)->handleBusReset(); 229 242 } 243 m_avDevicesLock->Unlock(); 230 244 231 245 // notify the streamprocessormanager of the busreset … … 243 257 244 258 // notify any clients 245 for ( busreset_notif_vec_t::iterator it = m_busResetNotifiers.begin(); 246 it != m_busResetNotifiers.end(); 259 signalNotifiers(m_busResetNotifiers); 260 261 // display the new state 262 showDeviceInfo(); 263 } 264 265 void 266 DeviceManager::signalNotifiers(notif_vec_t& list) 267 { 268 for ( notif_vec_t::iterator it = list.begin(); 269 it != list.end(); 247 270 ++it ) 248 271 { … … 251 274 ( *func )(); 252 275 } 253 // display the new state 254 showDeviceInfo(); 255 } 256 257 bool 258 DeviceManager::registerBusresetNotification(Util::Functor *handler) 276 } 277 278 bool 279 DeviceManager::registerNotification(notif_vec_t& list, Util::Functor *handler) 259 280 { 260 281 debugOutput( DEBUG_LEVEL_VERBOSE, "register %p...\n", handler); 261 282 assert(handler); 262 for ( busreset_notif_vec_t::iterator it = m_busResetNotifiers.begin();263 it != m_busResetNotifiers.end();283 for ( notif_vec_t::iterator it = list.begin(); 284 it != list.end(); 264 285 ++it ) 265 286 { … … 269 290 } 270 291 } 271 m_busResetNotifiers.push_back(handler);292 list.push_back(handler); 272 293 return true; 273 294 } 274 295 275 296 bool 276 DeviceManager::unregister BusresetNotification(Util::Functor *handler)297 DeviceManager::unregisterNotification(notif_vec_t& list, Util::Functor *handler) 277 298 { 278 299 debugOutput( DEBUG_LEVEL_VERBOSE, "unregister %p...\n", handler); 279 300 assert(handler); 280 301 281 for ( busreset_notif_vec_t::iterator it = m_busResetNotifiers.begin();282 it != m_busResetNotifiers.end();302 for ( notif_vec_t::iterator it = list.begin(); 303 it != list.end(); 283 304 ++it ) 284 305 { 285 306 if ( *it == handler ) { 286 m_busResetNotifiers.erase(it);307 list.erase(it); 287 308 return true; 288 309 } … … 306 327 307 328 setVerboseLevel(getDebugLevel()); 329 330 // FIXME: it could be that a 1394service has disappeared (cardbus) 308 331 309 332 ConfigRomVector configRoms; … … 342 365 } 343 366 367 368 // notify that we are going to manipulate the list 369 signalNotifiers(m_preUpdateNotifiers); 370 m_avDevicesLock->Lock(); // make sure nobody starts using the list 344 371 if(rediscover) { 372 345 373 FFADODeviceVector discovered_devices_on_bus; 346 374 for ( FFADODeviceVectorIterator it = m_avDevices.begin(); … … 538 566 } 539 567 showDeviceInfo(); 540 return true; 568 541 569 } else { // slave mode 570 // notify any clients 571 signalNotifiers(m_preUpdateNotifiers); 542 572 Ieee1394Service *portService = m_1394Services.at(0); 543 573 fb_nodeid_t nodeId = portService->getLocalNodeId(); … … 560 590 } 561 591 592 // remove any already present devices 593 for ( FFADODeviceVectorIterator it = m_avDevices.begin(); 594 it != m_avDevices.end(); 595 ++it ) 596 { 597 if (!deleteElement(*it)) { 598 debugWarning("failed to remove AvDevice from Control::Container\n"); 599 } 600 delete *it; 601 } 602 603 m_avDevices.clear(); 604 605 // get the slave driver 562 606 FFADODevice* avDevice = getSlaveDriver( configRom ); 563 607 if ( avDevice ) { … … 585 629 586 630 debugOutput( DEBUG_LEVEL_NORMAL, "discovery finished...\n" ); 587 return true; 588 } 631 } 632 633 m_avDevicesLock->Unlock(); 634 // notify any clients 635 signalNotifiers(m_postUpdateNotifiers); 636 return true; 589 637 } 590 638 trunk/libffado/src/devicemanager.h
r1154 r1163 37 37 38 38 #include "libutil/Functors.h" 39 #include "libutil/Mutex.h" 39 40 40 41 #include <vector> … … 105 106 106 107 void ignoreBusResets(bool b) {m_ignore_busreset = b;}; 107 bool registerBusresetNotification(Util::Functor *); 108 bool unregisterBusresetNotification(Util::Functor *); 108 bool registerBusresetNotification(Util::Functor *f) 109 {return registerNotification(m_busResetNotifiers, f);}; 110 bool unregisterBusresetNotification(Util::Functor *f) 111 {return unregisterNotification(m_busResetNotifiers, f);}; 112 113 bool registerPreUpdateNotification(Util::Functor *f) 114 {return registerNotification(m_preUpdateNotifiers, f);}; 115 bool unregisterPreUpdateNotification(Util::Functor *f) 116 {return unregisterNotification(m_preUpdateNotifiers, f);}; 117 118 bool registerPostUpdateNotification(Util::Functor *f) 119 {return registerNotification(m_postUpdateNotifiers, f);}; 120 bool unregisterPostUpdateNotification(Util::Functor *f) 121 {return unregisterNotification(m_postUpdateNotifiers, f);}; 109 122 110 123 void showDeviceInfo(); … … 131 144 FunctorVector m_busreset_functors; 132 145 146 // the lock protecting the device list 147 Util::Mutex* m_avDevicesLock; 148 // the lock to serialize bus reset handling 149 Util::Mutex* m_BusResetLock; 150 133 151 public: // FIXME: this should be better 134 152 Streaming::StreamProcessorManager& getStreamProcessorManager() … … 140 158 bool m_ignore_busreset; 141 159 142 typedef std::vector< Util::Functor* > busreset_notif_vec_t; 143 busreset_notif_vec_t m_busResetNotifiers; 160 typedef std::vector< Util::Functor* > notif_vec_t; 161 notif_vec_t m_busResetNotifiers; 162 notif_vec_t m_preUpdateNotifiers; 163 notif_vec_t m_postUpdateNotifiers; 164 165 bool registerNotification(notif_vec_t&, Util::Functor *); 166 bool unregisterNotification(notif_vec_t&, Util::Functor *); 167 void signalNotifiers(notif_vec_t& list); 144 168 145 169 protected: trunk/libffado/src/libcontrol/Element.cpp
r1160 r1163 112 112 } 113 113 114 bool 115 Element::addSignalHandler( SignalFunctor* functor ) 116 { 117 debugOutput(DEBUG_LEVEL_VERBOSE, "Adding signal handler (%p)\n", functor); 118 m_signalHandlers.push_back( functor ); 119 return true; 120 } 121 122 bool 123 Element::remSignalHandler( SignalFunctor* functor ) 124 { 125 debugOutput(DEBUG_LEVEL_VERBOSE, "Removing signal handler (%p)\n", functor); 126 127 for ( std::vector< SignalFunctor* >::iterator it = m_signalHandlers.begin(); 128 it != m_signalHandlers.end(); 129 ++it ) 130 { 131 if ( *it == functor ) { 132 debugOutput(DEBUG_LEVEL_VERBOSE, " found\n"); 133 m_signalHandlers.erase( it ); 134 return true; 135 } 136 } 137 debugOutput(DEBUG_LEVEL_VERBOSE, " not found\n"); 138 return false; 139 } 140 141 bool 142 Element::emitSignal(int id, int value) 143 { 144 for ( std::vector< SignalFunctor* >::iterator it = m_signalHandlers.begin(); 145 it != m_signalHandlers.end(); 146 ++it ) 147 { 148 SignalFunctor *f = *it; 149 if(f && f->m_id == id) (*f)(value); 150 } 151 return true; 152 } 153 114 154 //// --- Container --- //// 115 155 Container::Container(Element *p) … … 170 210 171 211 m_Children.push_back(e); 212 // unlock before emitting the signal 213 lock.earlyUnlock(); 214 emitSignal(eS_Updated, m_Children.size()); 172 215 return true; 173 216 } … … 187 230 if(*it == e) { 188 231 m_Children.erase(it); 232 // unlock before emitting the signal 233 lock.earlyUnlock(); 234 emitSignal(eS_Updated, m_Children.size()); 189 235 return true; 190 236 } … … 204 250 if (delete_pointers) delete e; 205 251 } 252 253 // unlock before emitting the signal 254 lock.earlyUnlock(); 255 emitSignal(eS_Updated, m_Children.size()); 206 256 return true; 207 257 } trunk/libffado/src/libcontrol/Element.h
r1158 r1163 31 31 32 32 #include "libutil/Mutex.h" 33 #include "libutil/Functors.h" 33 34 34 35 namespace Control { 36 37 class Element; 38 39 /*! 40 @brief Base class for control signal functors 41 42 This class should be subclassed to implement ffado control signal handlers. 43 */ 44 class SignalFunctor 45 { 46 friend class Element; 47 public: 48 SignalFunctor(int signal_id) 49 : m_id(signal_id) {}; 50 virtual ~SignalFunctor() {} 51 52 virtual void operator() (int arg) = 0; 53 protected: 54 int m_id; 55 }; 35 56 36 57 /*! … … 66 87 virtual void unlockControl(); 67 88 89 /** 90 * Update signal handler 91 */ 92 bool addSignalHandler( SignalFunctor* functor ); 93 bool remSignalHandler( SignalFunctor* functor ); 94 68 95 virtual void show(); 69 96 … … 75 102 76 103 protected: 104 bool emitSignal(int id, int value); 77 105 Util::Mutex& getLock(); 78 106 … … 83 111 std::string m_Label; 84 112 std::string m_Description; 85 113 86 114 uint64_t m_id; 115 std::vector< SignalFunctor* > m_signalHandlers; 87 116 88 117 protected: … … 135 164 virtual void setVerboseLevel(int l); 136 165 166 enum eSignals { 167 eS_Updated, 168 }; 169 137 170 protected: 138 171 ElementVector m_Children; trunk/libffado/src/libieee1394/ieee1394service.cpp
r1161 r1163 155 155 void 156 156 Ieee1394Service::doBusReset() { 157 debugOutput(DEBUG_LEVEL_VERBOSE, "Issue bus reset on service %p (port %d).\n", this, getPort()); 157 158 raw1394_reset_bus(m_handle); 158 159 } trunk/libffado/src/libutil/Mutex.h
r1045 r1163 59 59 MutexLockHelper(Mutex &m) 60 60 : m_mutex( m ) 61 , m_early_unlocked(false) 61 62 {m.Lock();}; 62 virtual ~MutexLockHelper() {m_mutex.Unlock();}; 63 virtual ~MutexLockHelper() 64 {if(!m_early_unlocked) m_mutex.Unlock();}; 65 66 /** 67 * Allows to unlock the mutex before the object is 68 * destroyed 69 */ 70 void earlyUnlock() 71 {m_early_unlocked=true; m_mutex.Unlock();}; 63 72 private: 64 73 Mutex &m_mutex; 74 bool m_early_unlocked; 65 75 }; 66 76 trunk/libffado/support/dbus/control-interface.xml
r998 r1163 25 25 <arg type="s" name="name" direction="out"/> 26 26 </method> 27 <signal name="Updated"></signal> 27 28 </interface> 28 29 trunk/libffado/support/dbus/controlserver.cpp
r1158 r1163 27 27 #include "libcontrol/MatrixMixer.h" 28 28 #include "libutil/Time.h" 29 #include "libutil/PosixMutex.h" 29 30 30 31 namespace DBusControl { … … 33 34 34 35 // --- Element 35 Element::Element( DBus::Connection& connection, std::string p, Control::Element &slave)36 Element::Element( DBus::Connection& connection, std::string p, Element* parent, Control::Element &slave) 36 37 : DBus::ObjectAdaptor(connection, p) 37 , m_Slave(slave) 38 , m_Parent(parent) 39 , m_Slave(slave) 40 , m_UpdateLock( NULL ) 38 41 { 39 42 debugOutput( DEBUG_LEVEL_VERBOSE, "Created Element on '%s'\n", 40 43 path().c_str() ); 44 // allocate a lock 45 if(parent == NULL) { 46 m_UpdateLock = new Util::PosixMutex(); 47 } else { 48 m_UpdateLock = NULL; 49 } 50 // set verbose level AFTER allocating the lock 41 51 setVerboseLevel(m_Slave.getVerboseLevel()); 52 } 53 54 void Element::setVerboseLevel(int i) 55 { 56 setDebugLevel(i); 57 if(m_UpdateLock) m_UpdateLock->setVerboseLevel(i); 58 } 59 60 void 61 Element::Lock() 62 { 63 if(m_Parent) { 64 m_Parent->Lock(); 65 } else { 66 m_UpdateLock->Lock(); 67 } 68 } 69 70 void 71 Element::Unlock() 72 { 73 if(m_Parent) { 74 m_Parent->Unlock(); 75 } else { 76 m_UpdateLock->Unlock(); 77 } 78 } 79 80 Util::Mutex* 81 Element::getLock() 82 { 83 if(m_Parent) { 84 return m_Parent->getLock(); 85 } else { 86 return m_UpdateLock; 87 } 42 88 } 43 89 … … 67 113 68 114 // --- Container 69 Container::Container( DBus::Connection& connection, std::string p, Control::Container &slave)70 : Element(connection, p, slave)115 Container::Container( DBus::Connection& connection, std::string p, Element* parent, Control::Container &slave) 116 : Element(connection, p, parent, slave) 71 117 , m_Slave(slave) 72 118 { … … 74 120 path().c_str() ); 75 121 76 // add children for the slave container 77 const Control::ElementVector elements = slave.getElementVector(); 78 for ( Control::ConstElementVectorIterator it = elements.begin(); 79 it != elements.end(); 80 ++it ) 81 { 82 Element *e=createHandler(*(*it)); 83 if (e) { 84 m_Children.push_back(e); 85 } else { 86 debugWarning("Failed to create handler for Control::Element %s\n", 87 (*it)->getName().c_str()); 122 setDebugLevel(slave.getVerboseLevel()); 123 124 // register an update signal handler 125 m_updateFunctor = new MemberSignalFunctor< Container*, 126 void (Container::*)(int) > 127 ( this, &Container::updated, (int)Control::Container::eS_Updated ); 128 if(m_updateFunctor) { 129 if(!slave.addSignalHandler(m_updateFunctor)) { 130 debugWarning("Could not add update signal functor\n"); 88 131 } 89 } 90 slave.releaseElementVector(); 132 } else { 133 debugWarning("Could not create update signal functor\n"); 134 } 135 136 // build the initial tree 137 m_Slave = slave; 138 updateTree(); 91 139 } 92 140 93 141 Container::~Container() { 142 debugOutput( DEBUG_LEVEL_VERBOSE, "Deleting Container on '%s'\n", 143 path().c_str() ); 144 if(m_updateFunctor) { 145 if(!m_Slave.remSignalHandler(m_updateFunctor)) { 146 debugWarning("Could not remove update signal functor\n"); 147 } 148 } 149 delete m_updateFunctor; 150 94 151 for ( ElementVectorIterator it = m_Children.begin(); 95 152 it != m_Children.end(); … … 97 154 { 98 155 delete (*it); 156 } 157 } 158 159 void 160 Container::setVerboseLevel(int i) 161 { 162 for ( ElementVectorIterator it = m_Children.begin(); 163 it != m_Children.end(); 164 ++it ) 165 { 166 (*it)->setVerboseLevel(i); 99 167 } 100 168 } … … 117 185 } else return ""; 118 186 } 119 187 // Util::MutexLockHelper lock(*m_access_lock); 188 189 // NOTE: call with access lock held! 190 void 191 Container::updateTree() 192 { 193 bool something_changed = false; 194 debugOutput( DEBUG_LEVEL_VERBOSE, "Updating tree...\n"); 195 debugOutput( DEBUG_LEVEL_VERBOSE, "Add handlers for elements...\n"); 196 // add handlers for the slaves that don't have one yet 197 const Control::ElementVector elements = m_Slave.getElementVector(); 198 for ( Control::ConstElementVectorIterator it = elements.begin(); 199 it != elements.end(); 200 ++it ) 201 { 202 Element *e = findElementForControl((*it)); 203 if(e == NULL) { // element not in tree 204 e = createHandler(this, *(*it)); 205 if (e) { 206 e->setVerboseLevel(getDebugLevel()); 207 m_Children.push_back(e); 208 debugOutput( DEBUG_LEVEL_VERBOSE, "Created handler %p for Control::Element %s...\n", 209 e, (*it)->getName().c_str()); 210 something_changed = true; 211 } else { 212 debugWarning("Failed to create handler for Control::Element %s\n", 213 (*it)->getName().c_str()); 214 } 215 } else { 216 // element already present 217 debugOutput( DEBUG_LEVEL_VERBOSE, "Already have handler (%p) for Control::Element %s...\n", 218 e, (*it)->getName().c_str()); 219 } 220 } 221 222 debugOutput( DEBUG_LEVEL_VERBOSE, "Remove handlers without element...\n"); 223 std::vector<Element *> to_remove; 224 // remove handlers that don't have a slave anymore 225 for ( ElementVectorIterator it = m_Children.begin(); 226 it != m_Children.end(); 227 ++it ) 228 { 229 Element *e = *it; 230 bool found = false; 231 for ( Control::ConstElementVectorIterator it2 = elements.begin(); 232 it2 != elements.end(); 233 ++it2 ) 234 { 235 if(&(e)->m_Slave == *it2) { 236 found = true; 237 debugOutput( DEBUG_LEVEL_VERBOSE, "Slave for handler %p at %s is present: Control::Element %s...\n", 238 e, e->path().c_str(), (*it)->getName().c_str()); 239 break; 240 } 241 } 242 243 if (!found) { 244 debugOutput(DEBUG_LEVEL_VERBOSE, 245 "going to remove handler %p on path %s since slave is gone\n", 246 e, e->path().c_str()); 247 // can't remove while iterating 248 to_remove.push_back(e); 249 something_changed = true; 250 } 251 } 252 // do the actual remove 253 while(to_remove.size()) { 254 Element * e = *(to_remove.begin()); 255 removeElement(e); 256 to_remove.erase(to_remove.begin()); 257 } 258 m_Slave.releaseElementVector(); 259 260 if(something_changed) { 261 debugOutput(DEBUG_LEVEL_VERBOSE, 262 "send dbus signal for path %s since something changed\n", 263 path().c_str()); 264 // send a dbus signal 265 Updated(); 266 } 267 } 268 269 void 270 Container::removeElement(Element *e) 271 { 272 debugOutput(DEBUG_LEVEL_VERBOSE, 273 "removing handler %p on path %s\n", 274 path().c_str(), e); 275 for ( ElementVectorIterator it = m_Children.begin(); 276 it != m_Children.end(); 277 ++it ) 278 { 279 if(*it == e) { 280 m_Children.erase(it); 281 delete e; 282 return; 283 } 284 } 285 debugError("BUG: Element %p not found!\n", e); 286 } 287 288 // NOTE: call with access lock held! 289 Element * 290 Container::findElementForControl(Control::Element *e) 291 { 292 for ( ElementVectorIterator it = m_Children.begin(); 293 it != m_Children.end(); 294 ++it ) 295 { 296 if(&(*it)->m_Slave == e) return (*it); 297 } 298 return NULL; 299 } 300 301 void 302 Container::updated(int new_nb_elements) 303 { 304 debugOutput( DEBUG_LEVEL_VERBOSE, "Got updated signal, new count='%d'\n", 305 new_nb_elements ); 306 // we lock the tree first 307 Lock(); 308 // update our tree 309 updateTree(); 310 Unlock(); 311 } 120 312 121 313 /** … … 123 315 */ 124 316 Element * 125 Container::createHandler( Control::Element& e) {317 Container::createHandler(Element *parent, Control::Element& e) { 126 318 debugOutput( DEBUG_LEVEL_VERBOSE, "Creating handler for '%s'\n", 127 319 e.getName().c_str() ); … … 131 323 132 324 return new Container(conn(), std::string(path()+"/"+e.getName()), 133 *dynamic_cast<Control::Container *>(&e));325 parent, *dynamic_cast<Control::Container *>(&e)); 134 326 } 135 327 … … 138 330 139 331 return new Continuous(conn(), std::string(path()+"/"+e.getName()), 140 *dynamic_cast<Control::Continuous *>(&e));332 parent, *dynamic_cast<Control::Continuous *>(&e)); 141 333 } 142 334 … … 145 337 146 338 return new Discrete(conn(), std::string(path()+"/"+e.getName()), 147 *dynamic_cast<Control::Discrete *>(&e));339 parent, *dynamic_cast<Control::Discrete *>(&e)); 148 340 } 149 341 … … 152 344 153 345 return new Text(conn(), std::string(path()+"/"+e.getName()), 154 *dynamic_cast<Control::Text *>(&e));346 parent, *dynamic_cast<Control::Text *>(&e)); 155 347 } 156 348 … … 159 351 160 352 return new Register(conn(), std::string(path()+"/"+e.getName()), 161 *dynamic_cast<Control::Register *>(&e));353 parent, *dynamic_cast<Control::Register *>(&e)); 162 354 } 163 355 … … 168 360 169 361 return new AttributeEnum(conn(), std::string(path()+"/"+e.getName()), 170 *dynamic_cast<Control::AttributeEnum *>(&e));362 parent, *dynamic_cast<Control::AttributeEnum *>(&e)); 171 363 } 172 364 … … 175 367 176 368 return new Enum(conn(), std::string(path()+"/"+e.getName()), 177 *dynamic_cast<Control::Enum *>(&e));369 parent, *dynamic_cast<Control::Enum *>(&e)); 178 370 } 179 371 … … 182 374 183 375 return new ConfigRomX(conn(), std::string(path()+"/"+e.getName()), 184 *dynamic_cast<ConfigRom *>(&e));376 parent, *dynamic_cast<ConfigRom *>(&e)); 185 377 } 186 378 … … 189 381 190 382 return new MatrixMixer(conn(), std::string(path()+"/"+e.getName()), 191 *dynamic_cast<Control::MatrixMixer *>(&e));383 parent, *dynamic_cast<Control::MatrixMixer *>(&e)); 192 384 } 193 385 194 386 debugOutput( DEBUG_LEVEL_VERBOSE, "Source is a Control::Element\n"); 195 return new Element(conn(), std::string(path()+"/"+e.getName()), e);387 return new Element(conn(), std::string(path()+"/"+e.getName()), parent, e); 196 388 } 197 389 198 390 // --- Continuous 199 391 200 Continuous::Continuous( DBus::Connection& connection, std::string p, Control::Continuous &slave)201 : Element(connection, p, slave)392 Continuous::Continuous( DBus::Connection& connection, std::string p, Element* parent, Control::Continuous &slave) 393 : Element(connection, p, parent, slave) 202 394 , m_Slave(slave) 203 395 { … … 264 456 // --- Discrete 265 457 266 Discrete::Discrete( DBus::Connection& connection, std::string p, Control::Discrete &slave)267 : Element(connection, p, slave)458 Discrete::Discrete( DBus::Connection& connection, std::string p, Element* parent, Control::Discrete &slave) 459 : Element(connection, p, parent, slave) 268 460 , m_Slave(slave) 269 461 { … … 314 506 // --- Text 315 507 316 Text::Text( DBus::Connection& connection, std::string p, Control::Text &slave)317 : Element(connection, p, slave)508 Text::Text( DBus::Connection& connection, std::string p, Element* parent, Control::Text &slave) 509 : Element(connection, p, parent, slave) 318 510 , m_Slave(slave) 319 511 { … … 344 536 // --- Register 345 537 346 Register::Register( DBus::Connection& connection, std::string p, Control::Register &slave)347 : Element(connection, p, slave)538 Register::Register( DBus::Connection& connection, std::string p, Element* parent, Control::Register &slave) 539 : Element(connection, p, parent, slave) 348 540 , m_Slave(slave) 349 541 { … … 374 566 // --- Enum 375 567 376 Enum::Enum( DBus::Connection& connection, std::string p, Control::Enum &slave)377 : Element(connection, p, slave)568 Enum::Enum( DBus::Connection& connection, std::string p, Element* parent, Control::Enum &slave) 569 : Element(connection, p, parent, slave) 378 570 , m_Slave(slave) 379 571 { … … 414 606 415 607 // --- AttributeEnum 416 AttributeEnum::AttributeEnum( DBus::Connection& connection, std::string p, Control::AttributeEnum &slave)417 : Element(connection, p, slave)608 AttributeEnum::AttributeEnum( DBus::Connection& connection, std::string p, Element* parent, Control::AttributeEnum &slave) 609 : Element(connection, p, parent, slave) 418 610 , m_Slave(slave) 419 611 { … … 479 671 // --- ConfigRom 480 672 481 ConfigRomX::ConfigRomX( DBus::Connection& connection, std::string p, ConfigRom &slave)482 : Element(connection, p, slave)673 ConfigRomX::ConfigRomX( DBus::Connection& connection, std::string p, Element* parent, ConfigRom &slave) 674 : Element(connection, p, parent, slave) 483 675 , m_Slave(slave) 484 676 { … … 525 717 // --- MatrixMixer 526 718 527 MatrixMixer::MatrixMixer( DBus::Connection& connection, std::string p, Control::MatrixMixer &slave)528 : Element(connection, p, slave)719 MatrixMixer::MatrixMixer( DBus::Connection& connection, std::string p, Element* parent, Control::MatrixMixer &slave) 720 : Element(connection, p, parent, slave) 529 721 , m_Slave(slave) 530 722 { trunk/libffado/support/dbus/controlserver.h
r1158 r1163 33 33 #include "libcontrol/BasicElements.h" 34 34 #include "libieee1394/configrom.h" 35 #include "libutil/Mutex.h" 35 36 36 37 namespace Control { … … 39 40 40 41 namespace DBusControl { 42 43 class Element; 44 class Container; 45 46 template< typename CalleePtr, typename MemFunPtr > 47 class MemberSignalFunctor 48 : public Control::SignalFunctor 49 { 50 public: 51 MemberSignalFunctor( const CalleePtr& pCallee, 52 MemFunPtr pMemFun, 53 int pSignalId) 54 : Control::SignalFunctor( pSignalId ) 55 , m_pCallee( pCallee ) 56 , m_pMemFun( pMemFun ) 57 {} 58 59 virtual ~MemberSignalFunctor() 60 {} 61 62 virtual void operator() (int value) 63 { 64 ( ( *m_pCallee ).*m_pMemFun )(value); 65 } 66 private: 67 CalleePtr m_pCallee; 68 MemFunPtr m_pMemFun; 69 }; 41 70 42 71 class Element … … 45 74 , public DBus::ObjectAdaptor 46 75 { 76 friend class Container; // This should not be necessary since Container derives from Element 47 77 public: 48 78 49 79 Element( DBus::Connection& connection, 50 std::string p, 80 std::string p, Element *, 51 81 Control::Element &slave ); 52 82 … … 56 86 DBus::String getDescription( ); 57 87 58 void setVerboseLevel(int i) {setDebugLevel(i);}; 59 private: 60 Control::Element &m_Slave; 61 88 void setVerboseLevel(int i); 89 90 protected: 91 void Lock(); 92 void Unlock(); 93 Util::Mutex* getLock(); 94 95 Element * m_Parent; 96 Control::Element & m_Slave; 97 private: 98 Util::Mutex* m_UpdateLock; 62 99 protected: 63 100 DECLARE_DEBUG_MODULE; … … 73 110 public: 74 111 Container( DBus::Connection& connection, 75 std::string p, 112 std::string p, Element *, 76 113 Control::Container &slave ); 77 114 virtual ~Container(); 78 79 Element *createHandler(Control::Element& e);80 115 81 116 DBus::Int32 getNbElements( ); 82 117 DBus::String getElementName( const DBus::Int32& ); 83 118 84 private: 85 Control::Container &m_Slave; 86 ElementVector m_Children; 119 void updated(int new_nb_elements); 120 void setVerboseLevel(int i); 121 private: 122 Element *createHandler(Element *, Control::Element& e); 123 void updateTree(); 124 Element * findElementForControl(Control::Element *e); 125 void removeElement(Element *e); 126 127 Control::Container & m_Slave; 128 ElementVector m_Children; 129 Control::SignalFunctor * m_updateFunctor; 87 130 }; 88 131 … … 93 136 public: 94 137 Continuous( DBus::Connection& connection, 95 std::string p, 138 std::string p, Element *, 96 139 Control::Continuous &slave ); 97 140 … … 114 157 public: 115 158 Discrete( DBus::Connection& connection, 116 std::string p, 159 std::string p, Element *, 117 160 Control::Discrete &slave ); 118 161 … … 133 176 public: 134 177 Text( DBus::Connection& connection, 135 std::string p, 178 std::string p, Element *, 136 179 Control::Text &slave ); 137 180 … … 149 192 public: 150 193 Register( DBus::Connection& connection, 151 std::string p, 194 std::string p, Element *, 152 195 Control::Register &slave ); 153 196 … … 165 208 public: 166 209 Enum( DBus::Connection& connection, 167 std::string p, 210 std::string p, Element *, 168 211 Control::Enum &slave ); 169 212 … … 183 226 public: 184 227 AttributeEnum( DBus::Connection& connection, 185 std::string p, 228 std::string p, Element *, 186 229 Control::AttributeEnum &slave ); 187 230 … … 206 249 public: 207 250 ConfigRomX( DBus::Connection& connection, 208 std::string p, 251 std::string p, Element *, 209 252 ConfigRom &slave ); 210 253 … … 226 269 public: 227 270 MatrixMixer( DBus::Connection& connection, 228 std::string p, 271 std::string p, Element *, 229 272 Control::MatrixMixer &slave ); 230 273 trunk/libffado/support/dbus/ffado-dbus-server.cpp
r1158 r1163 204 204 205 205 void 206 busresetHandler() 207 { 208 // this is a race condition: the control tree becomes invalid since we 209 // are redetecting the devices, but the dispatcher still allows access. 210 // at this point. This has to be split up in two. 211 debugOutput( DEBUG_LEVEL_NORMAL, "notified of bus reset...\n" ); 206 preUpdateHandler() 207 { 208 debugOutput( DEBUG_LEVEL_NORMAL, "got pre-update notification...\n" ); 209 // stop receiving dbus events since the control structure is going to 210 // be changed 212 211 dispatcher.leave(); 213 214 // delete old container 215 delete container; 216 container = NULL; 217 218 // build new one 219 if(m_deviceManager) { 220 container = new DBusControl::Container(*global_conn, "/org/ffado/Control/DeviceManager", *m_deviceManager); 221 } else { 222 debugError("no device manager, bailing out\n"); 223 run=0; 224 } 212 } 213 214 void 215 postUpdateHandler() 216 { 217 debugOutput( DEBUG_LEVEL_NORMAL, "got post-update notification...\n" ); 218 // the signal handlers registered by the elements should have taken 219 // care of updating the control tree 220 221 // signal that we can start receiving dbus events again 225 222 sem_post(&run_sem); 226 223 } … … 272 269 } 273 270 274 // add busresethandler275 Util::Functor* tmp_busreset_functor = new Util::CallbackFunctor0< void (*)() >276 ( & busresetHandler, false );277 if ( ! tmp_busreset_functor ) {278 debugFatal( "Could not create busresethandler\n" );271 // add pre-update handler 272 Util::Functor* preupdate_functor = new Util::CallbackFunctor0< void (*)() > 273 ( &preUpdateHandler, false ); 274 if ( !preupdate_functor ) { 275 debugFatal( "Could not create pre-update handler\n" ); 279 276 return false; 280 277 } 281 if(!m_deviceManager->registerBusresetNotification(tmp_busreset_functor)) { 282 debugError("could not register busreset notifier"); 278 if(!m_deviceManager->registerPreUpdateNotification(preupdate_functor)) { 279 debugError("could not register pre-update notifier"); 280 } 281 // add post-update handler 282 Util::Functor* postupdate_functor = new Util::CallbackFunctor0< void (*)() > 283 ( &postUpdateHandler, false ); 284 if ( !postupdate_functor ) { 285 debugFatal( "Could not create post-update handler\n" ); 286 return false; 287 } 288 if(!m_deviceManager->registerPostUpdateNotification(postupdate_functor)) { 289 debugError("could not register post-update notifier"); 283 290 } 284 291 … … 293 300 conn.request_name("org.ffado.Control"); 294 301 295 container = new DBusControl::Container(conn, "/org/ffado/Control/DeviceManager", *m_deviceManager); 302 container = new DBusControl::Container(conn, "/org/ffado/Control/DeviceManager", 303 NULL, *m_deviceManager); 296 304 297 305 printMessage("DBUS test service running\n"); … … 301 309 debugOutput( DEBUG_LEVEL_NORMAL, "dispatching...\n"); 302 310 dispatcher.enter(); 311 debugOutput( DEBUG_LEVEL_NORMAL, " dispatcher exited...\n"); 303 312 sem_wait(&run_sem); 313 debugOutput( DEBUG_LEVEL_NORMAL, " activity handled...\n"); 304 314 } 305 315 306 if(!m_deviceManager->unregisterBusresetNotification(tmp_busreset_functor)) { 307 debugError("could not unregister busreset notifier"); 308 } 309 delete tmp_busreset_functor; 316 if(!m_deviceManager->unregisterPreUpdateNotification(preupdate_functor)) { 317 debugError("could not unregister pre update notifier"); 318 } 319 delete preupdate_functor; 320 if(!m_deviceManager->unregisterPostUpdateNotification(postupdate_functor)) { 321 debugError("could not unregister post update notifier"); 322 } 323 delete postupdate_functor; 310 324 delete container; 311 325 trunk/libffado/support/dbus/test-dbus-server.cpp
r1158 r1163 161 161 // the container is deleted before the children become invalid 162 162 DBusControl::Container *container 163 = new DBusControl::Container(conn, "/org/ffado/Control/Test/Container", cont);163 = new DBusControl::Container(conn, "/org/ffado/Control/Test/Container", NULL, cont); 164 164 165 165 dispatcher.enter(); trunk/libffado/support/mixer/ffadomixer.in
r1094 r1163 33 33 import time 34 34 import dbus 35 35 36 from qt import * 36 37 … … 170 171 self.dev = self.bus.get_object(self.servername, self.basepath) 171 172 self.iface = dbus.Interface(self.dev, dbus_interface='org.ffado.Control.Element.Container') 173 # signal reception does not work yet since we need a mainloop for that 174 # and qt3 doesn't provide one for python/dbus 175 #try: 176 #self.dev.connect_to_signal("Updated", self.updateSignal, \ 177 #dbus_interface="org.ffado.Control.Element.Container", arg0=self) 178 #except dbus.DBusException: 179 #traceback.print_exc() 180 181 #def updateSignal(self): 182 #print ("Received update signal") 172 183 173 184 def getNbDevices(self): 174 185 return self.iface.getNbElements() 175 186 def getDeviceName(self, idx): 176 return self.iface.getElementName(idx) 187 return self.iface.getElementName(idx) 188 177 189 178 190 class ConfigRomInterface: trunk/libffado/tests/test-ffado.cpp
r1162 r1163 186 186 debugOutput( DEBUG_LEVEL_NORMAL, "Debug output flushed...\n" ); 187 187 flushDebugOutput(); 188 188 189 189 return retval; 190 190 }