Changeset 1163

Show
Ignore:
Timestamp:
05/11/08 15:04:25 (13 years ago)
Author:
ppalmers
Message:

make dbus server handle busresets cleanly (fixes #102)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/libffado/src/devicemanager.cpp

    r1158 r1163  
    3737#include "debugmodule/debugmodule.h" 
    3838 
     39#include "libutil/PosixMutex.h" 
     40 
    3941#ifdef ENABLE_BEBOB 
    4042#include "bebob/bebob_avdevice.h" 
     
    8284DeviceManager::DeviceManager() 
    8385    : Control::Container(NULL, "devicemanager") // this is the control root node 
     86    , m_avDevicesLock( new Util::PosixMutex() ) 
     87    , m_BusResetLock( new Util::PosixMutex() ) 
    8488    , m_processorManager( new Streaming::StreamProcessorManager() ) 
    8589    , m_deviceStringParser( new DeviceStringParser() ) 
     
    9599DeviceManager::~DeviceManager() 
    96100{ 
     101    m_avDevicesLock->Lock(); // make sure nobody is using this 
    97102    for ( FFADODeviceVectorIterator it = m_avDevices.begin(); 
    98103          it != m_avDevices.end(); 
     
    104109        delete *it; 
    105110    } 
    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 
    108115    delete m_processorManager; 
    109116 
     
    114121        delete *it; 
    115122    } 
     123    delete m_BusResetLock; 
    116124 
    117125    for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin(); 
     
    214222DeviceManager::busresetHandler() 
    215223{ 
     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); 
    216227    debugOutput( DEBUG_LEVEL_VERBOSE, "Bus reset...\n" ); 
    217228    if(m_ignore_busreset) { 
     
    221232 
    222233    // FIXME: what port was the bus reset on? 
     234    // FIXME: what if the devices are gone? 
    223235    // propagate the bus reset to all avDevices 
     236    m_avDevicesLock->Lock(); // make sure nobody is using this 
    224237    for ( FFADODeviceVectorIterator it = m_avDevices.begin(); 
    225238          it != m_avDevices.end(); 
     
    228241        (*it)->handleBusReset(); 
    229242    } 
     243    m_avDevicesLock->Unlock(); 
    230244 
    231245    // notify the streamprocessormanager of the busreset 
     
    243257 
    244258    // 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 
     265void 
     266DeviceManager::signalNotifiers(notif_vec_t& list) 
     267
     268    for ( notif_vec_t::iterator it = list.begin(); 
     269          it != list.end(); 
    247270          ++it ) 
    248271    { 
     
    251274        ( *func )(); 
    252275    } 
    253     // display the new state 
    254     showDeviceInfo(); 
    255 
    256  
    257 bool 
    258 DeviceManager::registerBusresetNotification(Util::Functor *handler) 
     276
     277 
     278bool 
     279DeviceManager::registerNotification(notif_vec_t& list, Util::Functor *handler) 
    259280{ 
    260281    debugOutput( DEBUG_LEVEL_VERBOSE, "register %p...\n", handler); 
    261282    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(); 
    264285      ++it ) 
    265286    { 
     
    269290        } 
    270291    } 
    271     m_busResetNotifiers.push_back(handler); 
     292    list.push_back(handler); 
    272293    return true; 
    273294} 
    274295 
    275296bool 
    276 DeviceManager::unregisterBusresetNotification(Util::Functor *handler) 
     297DeviceManager::unregisterNotification(notif_vec_t& list, Util::Functor *handler) 
    277298{ 
    278299    debugOutput( DEBUG_LEVEL_VERBOSE, "unregister %p...\n", handler); 
    279300    assert(handler); 
    280301 
    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(); 
    283304      ++it ) 
    284305    { 
    285306        if ( *it == handler ) { 
    286             m_busResetNotifiers.erase(it); 
     307            list.erase(it); 
    287308            return true; 
    288309        } 
     
    306327 
    307328    setVerboseLevel(getDebugLevel()); 
     329 
     330    // FIXME: it could be that a 1394service has disappeared (cardbus) 
    308331 
    309332    ConfigRomVector configRoms; 
     
    342365    } 
    343366 
     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 
    344371    if(rediscover) { 
     372 
    345373        FFADODeviceVector discovered_devices_on_bus; 
    346374        for ( FFADODeviceVectorIterator it = m_avDevices.begin(); 
     
    538566        } 
    539567        showDeviceInfo(); 
    540         return true; 
     568 
    541569    } else { // slave mode 
     570        // notify any clients 
     571        signalNotifiers(m_preUpdateNotifiers); 
    542572        Ieee1394Service *portService = m_1394Services.at(0); 
    543573        fb_nodeid_t nodeId = portService->getLocalNodeId(); 
     
    560590        } 
    561591 
     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 
    562606        FFADODevice* avDevice = getSlaveDriver( configRom ); 
    563607        if ( avDevice ) { 
     
    585629 
    586630        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; 
    589637} 
    590638 
  • trunk/libffado/src/devicemanager.h

    r1154 r1163  
    3737 
    3838#include "libutil/Functors.h" 
     39#include "libutil/Mutex.h" 
    3940 
    4041#include <vector> 
     
    105106 
    106107    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);}; 
    109122 
    110123    void showDeviceInfo(); 
     
    131144    FunctorVector           m_busreset_functors; 
    132145 
     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 
    133151public: // FIXME: this should be better 
    134152    Streaming::StreamProcessorManager&  getStreamProcessorManager()  
     
    140158    bool                                m_ignore_busreset; 
    141159 
    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); 
    144168 
    145169protected: 
  • trunk/libffado/src/libcontrol/Element.cpp

    r1160 r1163  
    112112} 
    113113 
     114bool 
     115Element::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 
     122bool 
     123Element::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 
     141bool 
     142Element::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 
    114154//// --- Container --- //// 
    115155Container::Container(Element *p) 
     
    170210 
    171211    m_Children.push_back(e); 
     212    // unlock before emitting the signal 
     213    lock.earlyUnlock(); 
     214    emitSignal(eS_Updated, m_Children.size()); 
    172215    return true; 
    173216} 
     
    187230        if(*it == e) { 
    188231            m_Children.erase(it); 
     232            // unlock before emitting the signal 
     233            lock.earlyUnlock(); 
     234            emitSignal(eS_Updated, m_Children.size()); 
    189235            return true; 
    190236        } 
     
    204250        if (delete_pointers) delete e; 
    205251    } 
     252 
     253    // unlock before emitting the signal 
     254    lock.earlyUnlock(); 
     255    emitSignal(eS_Updated, m_Children.size()); 
    206256    return true; 
    207257} 
  • trunk/libffado/src/libcontrol/Element.h

    r1158 r1163  
    3131 
    3232#include "libutil/Mutex.h" 
     33#include "libutil/Functors.h" 
    3334 
    3435namespace Control { 
     36 
     37class 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*/ 
     44class SignalFunctor 
     45{ 
     46    friend class Element; 
     47public: 
     48    SignalFunctor(int signal_id)  
     49    : m_id(signal_id) {}; 
     50    virtual ~SignalFunctor() {} 
     51 
     52    virtual void operator() (int arg) = 0; 
     53protected: 
     54    int m_id; 
     55}; 
    3556 
    3657/*! 
     
    6687    virtual void unlockControl(); 
    6788 
     89    /** 
     90     * Update signal handler 
     91     */ 
     92    bool addSignalHandler( SignalFunctor* functor ); 
     93    bool remSignalHandler( SignalFunctor* functor ); 
     94 
    6895    virtual void show(); 
    6996 
     
    75102 
    76103protected: 
     104    bool            emitSignal(int id, int value); 
    77105    Util::Mutex&    getLock(); 
    78106 
     
    83111    std::string m_Label; 
    84112    std::string m_Description; 
    85      
     113 
    86114    uint64_t m_id; 
     115    std::vector< SignalFunctor* > m_signalHandlers; 
    87116 
    88117protected: 
     
    135164    virtual void setVerboseLevel(int l); 
    136165 
     166    enum eSignals { 
     167        eS_Updated, 
     168    }; 
     169 
    137170protected: 
    138171    ElementVector m_Children; 
  • trunk/libffado/src/libieee1394/ieee1394service.cpp

    r1161 r1163  
    155155void 
    156156Ieee1394Service::doBusReset() { 
     157    debugOutput(DEBUG_LEVEL_VERBOSE, "Issue bus reset on service %p (port %d).\n", this, getPort()); 
    157158    raw1394_reset_bus(m_handle); 
    158159} 
  • trunk/libffado/src/libutil/Mutex.h

    r1045 r1163  
    5959    MutexLockHelper(Mutex &m) 
    6060    : m_mutex( m ) 
     61    , m_early_unlocked(false) 
    6162      {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();}; 
    6372private: 
    6473    Mutex &m_mutex; 
     74    bool   m_early_unlocked; 
    6575}; 
    6676 
  • trunk/libffado/support/dbus/control-interface.xml

    r998 r1163  
    2525          <arg type="s" name="name" direction="out"/> 
    2626      </method> 
     27      <signal name="Updated"></signal> 
    2728  </interface> 
    2829 
  • trunk/libffado/support/dbus/controlserver.cpp

    r1158 r1163  
    2727#include "libcontrol/MatrixMixer.h" 
    2828#include "libutil/Time.h" 
     29#include "libutil/PosixMutex.h" 
    2930 
    3031namespace DBusControl { 
     
    3334 
    3435// --- Element 
    35 Element::Element( DBus::Connection& connection, std::string p, Control::Element &slave) 
     36Element::Element( DBus::Connection& connection, std::string p, Element* parent, Control::Element &slave) 
    3637: DBus::ObjectAdaptor(connection, p) 
    37 , m_Slave(slave) 
     38, m_Parent(parent) 
     39, m_Slave(slave) 
     40, m_UpdateLock( NULL ) 
    3841{ 
    3942    debugOutput( DEBUG_LEVEL_VERBOSE, "Created Element on '%s'\n", 
    4043                 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 
    4151    setVerboseLevel(m_Slave.getVerboseLevel()); 
     52} 
     53 
     54void Element::setVerboseLevel(int i) 
     55{ 
     56    setDebugLevel(i); 
     57    if(m_UpdateLock) m_UpdateLock->setVerboseLevel(i); 
     58} 
     59 
     60void 
     61Element::Lock() 
     62{ 
     63    if(m_Parent) { 
     64        m_Parent->Lock(); 
     65    } else { 
     66        m_UpdateLock->Lock(); 
     67    } 
     68} 
     69 
     70void 
     71Element::Unlock() 
     72{ 
     73    if(m_Parent) { 
     74        m_Parent->Unlock(); 
     75    } else { 
     76        m_UpdateLock->Unlock(); 
     77    } 
     78} 
     79 
     80Util::Mutex* 
     81Element::getLock() 
     82{ 
     83    if(m_Parent) { 
     84        return m_Parent->getLock(); 
     85    } else { 
     86        return m_UpdateLock; 
     87    } 
    4288} 
    4389 
     
    67113 
    68114// --- Container 
    69 Container::Container( DBus::Connection& connection, std::string p, Control::Container &slave) 
    70 : Element(connection, p, slave) 
     115Container::Container( DBus::Connection& connection, std::string p, Element* parent, Control::Container &slave) 
     116: Element(connection, p, parent, slave) 
    71117, m_Slave(slave) 
    72118{ 
     
    74120                 path().c_str() ); 
    75121 
    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"); 
    88131        } 
    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(); 
    91139} 
    92140 
    93141Container::~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 
    94151    for ( ElementVectorIterator it = m_Children.begin(); 
    95152      it != m_Children.end(); 
     
    97154    { 
    98155        delete (*it); 
     156    } 
     157} 
     158 
     159void 
     160Container::setVerboseLevel(int i) 
     161{ 
     162    for ( ElementVectorIterator it = m_Children.begin(); 
     163      it != m_Children.end(); 
     164      ++it ) 
     165    { 
     166        (*it)->setVerboseLevel(i); 
    99167    } 
    100168} 
     
    117185    } else return ""; 
    118186} 
    119  
     187//     Util::MutexLockHelper lock(*m_access_lock); 
     188 
     189// NOTE: call with access lock held! 
     190void 
     191Container::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 
     269void 
     270Container::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! 
     289Element * 
     290Container::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 
     301void 
     302Container::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
    120312 
    121313/** 
     
    123315 */ 
    124316Element * 
    125 Container::createHandler(Control::Element& e) { 
     317Container::createHandler(Element *parent, Control::Element& e) { 
    126318    debugOutput( DEBUG_LEVEL_VERBOSE, "Creating handler for '%s'\n", 
    127319                 e.getName().c_str() ); 
     
    131323         
    132324        return new Container(conn(), std::string(path()+"/"+e.getName()),  
    133             *dynamic_cast<Control::Container *>(&e)); 
     325            parent, *dynamic_cast<Control::Container *>(&e)); 
    134326    } 
    135327     
     
    138330         
    139331        return new Continuous(conn(), std::string(path()+"/"+e.getName()), 
    140             *dynamic_cast<Control::Continuous *>(&e)); 
     332            parent, *dynamic_cast<Control::Continuous *>(&e)); 
    141333    } 
    142334     
     
    145337         
    146338        return new Discrete(conn(), std::string(path()+"/"+e.getName()), 
    147             *dynamic_cast<Control::Discrete *>(&e)); 
     339            parent, *dynamic_cast<Control::Discrete *>(&e)); 
    148340    } 
    149341     
     
    152344         
    153345        return new Text(conn(), std::string(path()+"/"+e.getName()), 
    154             *dynamic_cast<Control::Text *>(&e)); 
     346            parent, *dynamic_cast<Control::Text *>(&e)); 
    155347    } 
    156348 
     
    159351         
    160352        return new Register(conn(), std::string(path()+"/"+e.getName()), 
    161             *dynamic_cast<Control::Register *>(&e)); 
     353            parent, *dynamic_cast<Control::Register *>(&e)); 
    162354    } 
    163355 
     
    168360         
    169361        return new AttributeEnum(conn(), std::string(path()+"/"+e.getName()), 
    170             *dynamic_cast<Control::AttributeEnum *>(&e)); 
     362            parent, *dynamic_cast<Control::AttributeEnum *>(&e)); 
    171363    } 
    172364     
     
    175367         
    176368        return new Enum(conn(), std::string(path()+"/"+e.getName()), 
    177             *dynamic_cast<Control::Enum *>(&e)); 
     369            parent, *dynamic_cast<Control::Enum *>(&e)); 
    178370    } 
    179371     
     
    182374         
    183375        return new ConfigRomX(conn(), std::string(path()+"/"+e.getName()), 
    184             *dynamic_cast<ConfigRom *>(&e)); 
     376            parent, *dynamic_cast<ConfigRom *>(&e)); 
    185377    } 
    186378     
     
    189381         
    190382        return new MatrixMixer(conn(), std::string(path()+"/"+e.getName()), 
    191             *dynamic_cast<Control::MatrixMixer *>(&e)); 
     383            parent, *dynamic_cast<Control::MatrixMixer *>(&e)); 
    192384    } 
    193385     
    194386    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); 
    196388} 
    197389 
    198390// --- Continuous 
    199391 
    200 Continuous::Continuous( DBus::Connection& connection, std::string p, Control::Continuous &slave) 
    201 : Element(connection, p, slave) 
     392Continuous::Continuous( DBus::Connection& connection, std::string p, Element* parent, Control::Continuous &slave) 
     393: Element(connection, p, parent, slave) 
    202394, m_Slave(slave) 
    203395{ 
     
    264456// --- Discrete 
    265457 
    266 Discrete::Discrete( DBus::Connection& connection, std::string p, Control::Discrete &slave) 
    267 : Element(connection, p, slave) 
     458Discrete::Discrete( DBus::Connection& connection, std::string p, Element* parent, Control::Discrete &slave) 
     459: Element(connection, p, parent, slave) 
    268460, m_Slave(slave) 
    269461{ 
     
    314506// --- Text 
    315507 
    316 Text::Text( DBus::Connection& connection, std::string p, Control::Text &slave) 
    317 : Element(connection, p, slave) 
     508Text::Text( DBus::Connection& connection, std::string p, Element* parent, Control::Text &slave) 
     509: Element(connection, p, parent, slave) 
    318510, m_Slave(slave) 
    319511{ 
     
    344536// --- Register 
    345537 
    346 Register::Register( DBus::Connection& connection, std::string p, Control::Register &slave) 
    347 : Element(connection, p, slave) 
     538Register::Register( DBus::Connection& connection, std::string p, Element* parent, Control::Register &slave) 
     539: Element(connection, p, parent, slave) 
    348540, m_Slave(slave) 
    349541{ 
     
    374566// --- Enum 
    375567 
    376 Enum::Enum( DBus::Connection& connection, std::string p, Control::Enum &slave) 
    377 : Element(connection, p, slave) 
     568Enum::Enum( DBus::Connection& connection, std::string p, Element* parent, Control::Enum &slave) 
     569: Element(connection, p, parent, slave) 
    378570, m_Slave(slave) 
    379571{ 
     
    414606 
    415607// --- AttributeEnum 
    416 AttributeEnum::AttributeEnum( DBus::Connection& connection, std::string p, Control::AttributeEnum &slave) 
    417 : Element(connection, p, slave) 
     608AttributeEnum::AttributeEnum( DBus::Connection& connection, std::string p, Element* parent, Control::AttributeEnum &slave) 
     609: Element(connection, p, parent, slave) 
    418610, m_Slave(slave) 
    419611{ 
     
    479671// --- ConfigRom 
    480672 
    481 ConfigRomX::ConfigRomX( DBus::Connection& connection, std::string p, ConfigRom &slave) 
    482 : Element(connection, p, slave) 
     673ConfigRomX::ConfigRomX( DBus::Connection& connection, std::string p, Element* parent, ConfigRom &slave) 
     674: Element(connection, p, parent, slave) 
    483675, m_Slave(slave) 
    484676{ 
     
    525717// --- MatrixMixer 
    526718 
    527 MatrixMixer::MatrixMixer( DBus::Connection& connection, std::string p, Control::MatrixMixer &slave) 
    528 : Element(connection, p, slave) 
     719MatrixMixer::MatrixMixer( DBus::Connection& connection, std::string p, Element* parent, Control::MatrixMixer &slave) 
     720: Element(connection, p, parent, slave) 
    529721, m_Slave(slave) 
    530722{ 
  • trunk/libffado/support/dbus/controlserver.h

    r1158 r1163  
    3333#include "libcontrol/BasicElements.h" 
    3434#include "libieee1394/configrom.h" 
     35#include "libutil/Mutex.h" 
    3536 
    3637namespace Control { 
     
    3940 
    4041namespace DBusControl { 
     42 
     43class Element; 
     44class Container; 
     45 
     46template< typename CalleePtr, typename MemFunPtr > 
     47class MemberSignalFunctor 
     48    : public Control::SignalFunctor 
     49{ 
     50public: 
     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        } 
     66private: 
     67    CalleePtr  m_pCallee; 
     68    MemFunPtr  m_pMemFun; 
     69}; 
    4170 
    4271class Element 
     
    4574, public DBus::ObjectAdaptor 
    4675{ 
     76friend class Container; // This should not be necessary since Container derives from Element 
    4777public: 
    4878 
    4979    Element( DBus::Connection& connection, 
    50              std::string p, 
     80             std::string p, Element *, 
    5181             Control::Element &slave ); 
    5282 
     
    5686    DBus::String getDescription( ); 
    5787 
    58     void setVerboseLevel(int i) {setDebugLevel(i);}; 
    59 private: 
    60     Control::Element &m_Slave; 
    61  
     88    void setVerboseLevel(int i); 
     89 
     90protected: 
     91    void Lock(); 
     92    void Unlock(); 
     93    Util::Mutex* getLock(); 
     94 
     95    Element *           m_Parent; 
     96    Control::Element &  m_Slave; 
     97private: 
     98    Util::Mutex*        m_UpdateLock; 
    6299protected: 
    63100    DECLARE_DEBUG_MODULE; 
     
    73110public: 
    74111    Container( DBus::Connection& connection, 
    75                   std::string p, 
     112                  std::string p, Element *, 
    76113                  Control::Container &slave ); 
    77114    virtual ~Container(); 
    78      
    79     Element *createHandler(Control::Element& e); 
    80115 
    81116    DBus::Int32 getNbElements( ); 
    82117    DBus::String getElementName( const DBus::Int32& ); 
    83118 
    84 private: 
    85     Control::Container &m_Slave; 
    86     ElementVector m_Children; 
     119    void updated(int new_nb_elements); 
     120    void setVerboseLevel(int i); 
     121private: 
     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; 
    87130}; 
    88131 
     
    93136public: 
    94137    Continuous( DBus::Connection& connection, 
    95                   std::string p, 
     138                  std::string p, Element *, 
    96139                  Control::Continuous &slave ); 
    97140     
     
    114157public: 
    115158    Discrete( DBus::Connection& connection, 
    116               std::string p, 
     159              std::string p, Element *, 
    117160              Control::Discrete &slave ); 
    118161     
     
    133176public: 
    134177    Text( DBus::Connection& connection, 
    135           std::string p, 
     178          std::string p, Element *, 
    136179          Control::Text &slave ); 
    137180 
     
    149192public: 
    150193    Register( DBus::Connection& connection, 
    151               std::string p, 
     194              std::string p, Element *, 
    152195              Control::Register &slave ); 
    153196     
     
    165208public: 
    166209    Enum( DBus::Connection& connection, 
    167           std::string p, 
     210          std::string p, Element *, 
    168211          Control::Enum &slave ); 
    169212     
     
    183226public: 
    184227    AttributeEnum( DBus::Connection& connection, 
    185                    std::string p, 
     228                   std::string p, Element *, 
    186229                   Control::AttributeEnum &slave ); 
    187230     
     
    206249public: 
    207250    ConfigRomX( DBus::Connection& connection, 
    208                   std::string p, 
     251                  std::string p, Element *, 
    209252                  ConfigRom &slave ); 
    210253 
     
    226269public: 
    227270    MatrixMixer(  DBus::Connection& connection, 
    228                   std::string p, 
     271                  std::string p, Element *, 
    229272                  Control::MatrixMixer &slave ); 
    230273 
  • trunk/libffado/support/dbus/ffado-dbus-server.cpp

    r1158 r1163  
    204204 
    205205void 
    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" ); 
     206preUpdateHandler() 
     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 
    212211    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 
     214void 
     215postUpdateHandler() 
     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 
    225222    sem_post(&run_sem); 
    226223} 
     
    272269        } 
    273270 
    274         // add busreset handler 
    275         Util::Functor* tmp_busreset_functor = new Util::CallbackFunctor0< void (*)() > 
    276                     ( &busresetHandler, false ); 
    277         if ( !tmp_busreset_functor ) { 
    278             debugFatal( "Could not create busreset handler\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" ); 
    279276            return false; 
    280277        } 
    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"); 
    283290        } 
    284291 
     
    293300        conn.request_name("org.ffado.Control"); 
    294301 
    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); 
    296304         
    297305        printMessage("DBUS test service running\n"); 
     
    301309            debugOutput( DEBUG_LEVEL_NORMAL, "dispatching...\n"); 
    302310            dispatcher.enter(); 
     311            debugOutput( DEBUG_LEVEL_NORMAL, " dispatcher exited...\n"); 
    303312            sem_wait(&run_sem); 
     313            debugOutput( DEBUG_LEVEL_NORMAL, " activity handled...\n"); 
    304314        } 
    305315         
    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; 
    310324        delete container; 
    311325 
  • trunk/libffado/support/dbus/test-dbus-server.cpp

    r1158 r1163  
    161161    // the container is deleted before the children become invalid 
    162162    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); 
    164164 
    165165    dispatcher.enter(); 
  • trunk/libffado/support/mixer/ffadomixer.in

    r1094 r1163  
    3333import time 
    3434import dbus 
     35 
    3536from qt import * 
    3637 
     
    170171        self.dev = self.bus.get_object(self.servername, self.basepath) 
    171172        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") 
    172183 
    173184    def getNbDevices(self): 
    174185        return self.iface.getNbElements() 
    175186    def getDeviceName(self, idx): 
    176         return self.iface.getElementName(idx)   
     187        return self.iface.getElementName(idx) 
     188 
    177189 
    178190class ConfigRomInterface: 
  • trunk/libffado/tests/test-ffado.cpp

    r1162 r1163  
    186186    debugOutput( DEBUG_LEVEL_NORMAL, "Debug output flushed...\n" ); 
    187187    flushDebugOutput(); 
    188      
     188 
    189189    return retval; 
    190190}