diff --git a/.gitignore b/.gitignore
index 123da9aae877b89bf3a2d1f659a422bf1fe292c4..9b50f67f10d2b6e59dfb4137d2c73babf22fa0db 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,5 +69,9 @@ config_auto.h
 # Ignore temp files
 *~
 
+# Cscope/Ctags files
+cscope.*
+tags
+
 # IDE stuffs
 nbproject
diff --git a/daemon/src/account.cpp b/daemon/src/account.cpp
index af0b0689d7505b4b951704dce1c1919a00c85029..094eb1afc20d46ecf743ebf1df6c43599a40181b 100644
--- a/daemon/src/account.cpp
+++ b/daemon/src/account.cpp
@@ -32,8 +32,9 @@
 
 #include "account.h"
 #include "manager.h"
+#include "dbus/configurationmanager.h"
 
-Account::Account(const std::string& accountID, const std::string &type) :
+Account::Account(const std::string &accountID, const std::string &type) :
     accountID_(accountID)
     , username_()
     , hostname_()
@@ -54,8 +55,7 @@ Account::Account(const std::string& accountID, const std::string &type) :
 }
 
 Account::~Account()
-{
-}
+{}
 
 void Account::setRegistrationState(const RegistrationState &state)
 {
@@ -63,7 +63,8 @@ void Account::setRegistrationState(const RegistrationState &state)
         registrationState_ = state;
 
         // Notify the client
-        Manager::instance().connectionStatusNotification();
+        ConfigurationManager *c(Manager::instance().getDbusManager()->getConfigurationManager());
+        c->registrationStateChanged(accountID_, registrationState_);
     }
 }
 
diff --git a/daemon/src/audio/audiortp/audio_rtp_factory.cpp b/daemon/src/audio/audiortp/audio_rtp_factory.cpp
index 5ce37ce1f53c08fc342d4b60daff3beefc3173dd..2170b06e52a77e238fa1c4241ec4cc4bac363218 100644
--- a/daemon/src/audio/audiortp/audio_rtp_factory.cpp
+++ b/daemon/src/audio/audiortp/audio_rtp_factory.cpp
@@ -43,17 +43,19 @@
 namespace sfl {
 
 AudioRtpFactory::AudioRtpFactory(SIPCall *ca) : rtpSession_(NULL),
-    audioRtpThreadMutex_(), srtpEnabled_(false),
-    keyExchangeProtocol_(Symmetric), helloHashEnabled_(false),
-    remoteContext_(NULL), localContext_(NULL), ca_(ca)
+    audioRtpThreadMutex_(), srtpEnabled_(false), helloHashEnabled_(false),
+    cachedRemoteContext_(0), cachedLocalContext_(0), ca_(ca),
+    keyExchangeProtocol_(NONE)
 {}
 
 AudioRtpFactory::~AudioRtpFactory()
 {
     delete rtpSession_;
+    delete cachedLocalContext_;
+    delete cachedRemoteContext_;
 }
 
-void AudioRtpFactory::initAudioRtpConfig()
+void AudioRtpFactory::initConfig()
 {
     if (rtpSession_ != NULL)
         stop();
@@ -65,48 +67,48 @@ void AudioRtpFactory::initAudioRtpConfig()
     if (account) {
         srtpEnabled_ = account->getSrtpEnabled();
         std::string key(account->getSrtpKeyExchange());
-
-        if (key == "sdes")
-            keyExchangeProtocol_ = Sdes;
-        else if (key == "zrtp")
-            keyExchangeProtocol_ = Zrtp;
-        else
-            keyExchangeProtocol_ = Symmetric;
-
+        if (srtpEnabled_) {
+            if (key == "sdes")
+                keyExchangeProtocol_ = SDES;
+            else if (key == "zrtp")
+                keyExchangeProtocol_ = ZRTP;
+        } else {
+            keyExchangeProtocol_ = NONE;
+        }
         helloHashEnabled_ = account->getZrtpHelloHash();
     } else {
         srtpEnabled_ = false;
-        keyExchangeProtocol_ = Symmetric;
+        keyExchangeProtocol_ = NONE;
         helloHashEnabled_ = false;
     }
 }
 
-void AudioRtpFactory::initAudioSymmetricRtpSession()
+void AudioRtpFactory::initSession()
 {
     ost::MutexLock m(audioRtpThreadMutex_);
 
     if (srtpEnabled_) {
-        std::string zidFilename(Manager::instance().voipPreferences.getZidFile());
+        const std::string zidFilename(Manager::instance().voipPreferences.getZidFile());
 
         switch (keyExchangeProtocol_) {
 
-            case Zrtp:
-                rtpSession_ = new AudioZrtpSession(ca_, zidFilename);
+            case ZRTP:
+                rtpSession_ = new AudioZrtpSession(*ca_, zidFilename);
                 // TODO: be careful with that. The hello hash is computed asynchronously. Maybe it's
                 // not even available at that point.
                 if (helloHashEnabled_)
                     ca_->getLocalSDP()->setZrtpHash(static_cast<AudioZrtpSession *>(rtpSession_)->getHelloHash());
                 break;
 
-            case Sdes:
-                rtpSession_ = new AudioSrtpSession(ca_);
+            case SDES:
+                rtpSession_ = new AudioSrtpSession(*ca_);
                 break;
 
             default:
                 throw UnsupportedRtpSessionType("Unsupported Rtp Session Exception Type!");
         }
     } else
-        rtpSession_ = new AudioSymmetricRtpSession(ca_);
+        rtpSession_ = new AudioSymmetricRtpSession(*ca_);
 }
 
 void AudioRtpFactory::start(AudioCodec* audiocodec)
@@ -114,26 +116,17 @@ void AudioRtpFactory::start(AudioCodec* audiocodec)
     if (rtpSession_ == NULL)
         throw AudioRtpFactoryException("AudioRtpFactory: Error: RTP session was null when trying to start audio thread");
 
-    if (rtpSession_->getAudioRtpType() == Sdes)
-        if (localContext_ and remoteContext_)
-            static_cast<AudioSrtpSession *>(rtpSession_)->restoreCryptoContext(localContext_, remoteContext_);
+    if (keyExchangeProtocol_ == SDES and cachedLocalContext_ and cachedRemoteContext_)
+        static_cast<AudioSrtpSession *>(rtpSession_)->restoreCryptoContext(cachedLocalContext_, cachedRemoteContext_);
 
-    if (rtpSession_->startRtpThread(audiocodec) != 0)
-        throw AudioRtpFactoryException("AudioRtpFactory: Error: Failed to start AudioZrtpSession thread");
+    if (rtpSession_->startRtpThread(*audiocodec) != 0)
+        throw AudioRtpFactoryException("AudioRtpFactory: Error: Failed to start AudioRtpSession thread");
 }
 
 void AudioRtpFactory::stop()
 {
     ost::MutexLock mutex(audioRtpThreadMutex_);
 
-    if (rtpSession_ == NULL)
-        return;
-
-    if (rtpSession_->getAudioRtpType() == Sdes) {
-        localContext_ = static_cast<AudioSrtpSession*>(rtpSession_)->localCryptoCtx_;
-        remoteContext_ = static_cast<AudioSrtpSession*>(rtpSession_)->remoteCryptoCtx_;
-    }
-
     delete rtpSession_;
     rtpSession_ = NULL;
 }
@@ -151,7 +144,7 @@ void AudioRtpFactory::updateSessionMedia(AudioCodec *audiocodec)
     if (rtpSession_ == NULL)
         throw AudioRtpFactoryException("AudioRtpFactory: Error: rtpSession_ was null when trying to update IP address");
 
-    rtpSession_->updateSessionMedia(audiocodec);
+    rtpSession_->updateSessionMedia(*audiocodec);
 }
 
 void AudioRtpFactory::updateDestinationIpAddress()
@@ -162,7 +155,7 @@ void AudioRtpFactory::updateDestinationIpAddress()
 
 sfl::AudioZrtpSession * AudioRtpFactory::getAudioZrtpSession()
 {
-    if (rtpSession_->getAudioRtpType() == Zrtp)
+    if (keyExchangeProtocol_ == ZRTP)
         return static_cast<AudioZrtpSession *>(rtpSession_);
     else
         throw AudioRtpFactoryException("RTP: Error: rtpSession_ is NULL in getAudioZrtpSession");
@@ -170,17 +163,20 @@ sfl::AudioZrtpSession * AudioRtpFactory::getAudioZrtpSession()
 
 void sfl::AudioRtpFactory::initLocalCryptoInfo()
 {
-    if (rtpSession_ && rtpSession_->getAudioRtpType() == Sdes) {
-        static_cast<AudioSrtpSession *>(rtpSession_)->initLocalCryptoInfo();
-        ca_->getLocalSDP()->setLocalSdpCrypto(static_cast<AudioSrtpSession *>(rtpSession_)->getLocalCryptoInfo());
+    if (rtpSession_ && keyExchangeProtocol_ == SDES) {
+        AudioSrtpSession *srtp = static_cast<AudioSrtpSession*>(rtpSession_);
+        // the context is invalidated and deleted by the call to initLocalCryptoInfo
+        cachedLocalContext_ = srtp->initLocalCryptoInfo();
+        ca_->getLocalSDP()->setLocalSdpCrypto(srtp->getLocalCryptoInfo());
     }
 }
 
 void AudioRtpFactory::setRemoteCryptoInfo(sfl::SdesNegotiator& nego)
 {
-    if (rtpSession_ && rtpSession_->getAudioRtpType() == Sdes)
-        static_cast<AudioSrtpSession *>(rtpSession_)->setRemoteCryptoInfo(nego);
-    else
+    if (rtpSession_ and keyExchangeProtocol_ == SDES) {
+        AudioSrtpSession *srtp = static_cast<AudioSrtpSession *>(rtpSession_);
+        cachedRemoteContext_ = srtp->setRemoteCryptoInfo(nego);
+    } else
         throw AudioRtpFactoryException("RTP: Error: rtpSession_ is NULL in setRemoteCryptoInfo");
 }
 
diff --git a/daemon/src/audio/audiortp/audio_rtp_factory.h b/daemon/src/audio/audiortp/audio_rtp_factory.h
index c91f0e18641c6d47b8fe67cc7345f4fc4e7c7b35..9aa90d3b4d1a13112edb8623770b515c2003eb5d 100644
--- a/daemon/src/audio/audiortp/audio_rtp_factory.h
+++ b/daemon/src/audio/audiortp/audio_rtp_factory.h
@@ -62,15 +62,15 @@ class AudioRtpFactory {
         AudioRtpFactory(SIPCall *ca);
         ~AudioRtpFactory();
 
-        void initAudioRtpConfig();
+        void initConfig();
 
         /**
          * 	Lazy instantiation method. Create a new RTP session of a given
          * type according to the content of the configuration file.
          * @param ca A pointer on a SIP call
-         * @return A new AudioSymmetricRtpSession object
+         * @return A new AudioRtpSession object
          */
-        void initAudioSymmetricRtpSession();
+        void initSession();
 
         /**
          * Start the audio rtp thread of the type specified in the configuration
@@ -103,7 +103,7 @@ class AudioRtpFactory {
         void updateDestinationIpAddress();
 
         bool isSdesEnabled() const {
-            return srtpEnabled_ and keyExchangeProtocol_ == sfl::Sdes;
+            return srtpEnabled_ and keyExchangeProtocol_ == SDES;
         }
 
         /**
@@ -140,28 +140,26 @@ class AudioRtpFactory {
 
     private:
         NON_COPYABLE(AudioRtpFactory);
+        enum KeyExchangeProtocol { NONE, SDES, ZRTP };
         AudioRtpSession *rtpSession_;
         ost::Mutex audioRtpThreadMutex_;
 
-        // Field used when initializinga udio rtp session
+        // Field used when initializing audio rtp session
         // May be set manually or from config using initAudioRtpConfig
         bool srtpEnabled_;
 
-        // Field used when initializinga udio rtp session
-        // May be set manually or from config using initAudioRtpConfig
-        RtpMethod keyExchangeProtocol_;
-
         // Field used when initializinga udio rtp session
         // May be set manually or from config using initAudioRtpConfig
         bool helloHashEnabled_;
 
         /** Remote srtp crypto context to be set into incoming data queue. */
-        ost::CryptoContext *remoteContext_;
+        ost::CryptoContext *cachedRemoteContext_;
 
         /** Local srtp crypto context to be set into outgoing data queue. */
-        ost::CryptoContext *localContext_;
+        ost::CryptoContext *cachedLocalContext_;
 
         SIPCall *ca_;
+        KeyExchangeProtocol keyExchangeProtocol_;
 };
 }
 #endif // __AUDIO_RTP_FACTORY_H__
diff --git a/daemon/src/audio/audiortp/audio_rtp_record_handler.cpp b/daemon/src/audio/audiortp/audio_rtp_record_handler.cpp
index 8ce03be48914e6902196162e5b23d51cba85c0d1..99c5064d94a00d36bcfba5c137f3a9ff1848e312 100644
--- a/daemon/src/audio/audiortp/audio_rtp_record_handler.cpp
+++ b/daemon/src/audio/audiortp/audio_rtp_record_handler.cpp
@@ -67,13 +67,17 @@ AudioRtpRecord::~AudioRtpRecord()
 }
 
 
-AudioRtpRecordHandler::AudioRtpRecordHandler(SIPCall *ca) : audioRtpRecord_(), id_(ca->getCallId()), echoCanceller(ca->getMemoryPool()), gainController(8000, -10.0)
+AudioRtpRecordHandler::AudioRtpRecordHandler(SIPCall &call) :
+    audioRtpRecord_(),
+    id_(call.getCallId()),
+    echoCanceller(call.getMemoryPool()),
+    gainController(8000, -10.0)
 {}
 
 
 AudioRtpRecordHandler::~AudioRtpRecordHandler() {}
 
-void AudioRtpRecordHandler::setRtpMedia(AudioCodec* audioCodec)
+void AudioRtpRecordHandler::setRtpMedia(AudioCodec *audioCodec)
 {
     ost::MutexLock lock(audioRtpRecord_.audioCodecMutex_);
 
diff --git a/daemon/src/audio/audiortp/audio_rtp_record_handler.h b/daemon/src/audio/audiortp/audio_rtp_record_handler.h
index 9012049a133d1b279448835ba31e3c5d7bcb4a75..ac630e2872aac936f7aa05f8c73897c80e6b1296 100644
--- a/daemon/src/audio/audiortp/audio_rtp_record_handler.h
+++ b/daemon/src/audio/audiortp/audio_rtp_record_handler.h
@@ -103,7 +103,7 @@ class AudioRtpRecord {
 
 class AudioRtpRecordHandler {
     public:
-        AudioRtpRecordHandler(SIPCall *);
+        AudioRtpRecordHandler(SIPCall &);
         virtual ~AudioRtpRecordHandler();
 
         /**
diff --git a/daemon/src/audio/audiortp/audio_rtp_session.cpp b/daemon/src/audio/audiortp/audio_rtp_session.cpp
index a334d063c642eb2b0fae2005435d8d547b19525c..7a34d7ba82d94d4557502af243526e83d81154c4 100644
--- a/daemon/src/audio/audiortp/audio_rtp_session.cpp
+++ b/daemon/src/audio/audiortp/audio_rtp_session.cpp
@@ -43,29 +43,27 @@
 #include "manager.h"
 
 namespace sfl {
-AudioRtpSession::AudioRtpSession(SIPCall * sipcall, RtpMethod type, ost::RTPDataQueue *queue, ost::Thread *thread) :
-    AudioRtpRecordHandler(sipcall)
-    , ca_(sipcall)
-    , type_(type)
-    , remote_ip_()
-    , remote_port_(0)
+AudioRtpSession::AudioRtpSession(SIPCall &call, ost::RTPDataQueue &queue, ost::Thread &thread) :
+    AudioRtpRecordHandler(call)
+    , call_(call)
     , timestamp_(0)
     , timestampIncrement_(0)
-    , timestampCount_(0)
-    , isStarted_(false)
     , queue_(queue)
+    , isStarted_(false)
+    , remote_ip_()
+    , remote_port_(0)
+    , timestampCount_(0)
     , thread_(thread)
 {
-    assert(ca_);
-    queue_->setTypeOfService(ost::RTPDataQueue::tosEnhanced);
+    queue_.setTypeOfService(ost::RTPDataQueue::tosEnhanced);
 }
 
 AudioRtpSession::~AudioRtpSession()
 {
-    queue_->disableStack();
+    queue_.disableStack();
 }
 
-void AudioRtpSession::updateSessionMedia(AudioCodec *audioCodec)
+void AudioRtpSession::updateSessionMedia(AudioCodec &audioCodec)
 {
     int lastSamplingRate = audioRtpRecord_.codecSampleRate_;
 
@@ -80,9 +78,9 @@ void AudioRtpSession::updateSessionMedia(AudioCodec *audioCodec)
 
 }
 
-void AudioRtpSession::setSessionMedia(AudioCodec *audioCodec)
+void AudioRtpSession::setSessionMedia(AudioCodec &audioCodec)
 {
-    setRtpMedia(audioCodec);
+    setRtpMedia(&audioCodec);
 
     // store codec info locally
     int payloadType = getCodecPayloadType();
@@ -96,26 +94,28 @@ void AudioRtpSession::setSessionMedia(AudioCodec *audioCodec)
     else
         timestampIncrement_ = frameSize;
 
-    DEBUG("AudioRptSession: Codec payload: %d", payloadType);
-    DEBUG("AudioSymmetricRtpSession: Codec sampling rate: %d", smplRate);
-    DEBUG("AudioSymmetricRtpSession: Codec frame size: %d", frameSize);
-    DEBUG("AudioSymmetricRtpSession: RTP timestamp increment: %d", timestampIncrement_);
+    DEBUG("AudioRtpSession: Codec payload: %d", payloadType);
+    DEBUG("AudioRtpSession: Codec sampling rate: %d", smplRate);
+    DEBUG("AudioRtpSession: Codec frame size: %d", frameSize);
+    DEBUG("AudioRtpSession: RTP timestamp increment: %d", timestampIncrement_);
 
     if (payloadType == g722PayloadType) {
-        DEBUG("AudioSymmetricRtpSession: Setting G722 payload format");
-        queue_->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) payloadType, g722RtpClockRate));
+        DEBUG("AudioRtpSession: Setting G722 payload format");
+        queue_.setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) payloadType, g722RtpClockRate));
     } else {
         if (dynamic) {
-            DEBUG("AudioSymmetricRtpSession: Setting dynamic payload format");
-            queue_->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) payloadType, smplRate));
+            DEBUG("AudioRtpSession: Setting dynamic payload format");
+            queue_.setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) payloadType, smplRate));
         } else {
-            DEBUG("AudioSymmetricRtpSession: Setting static payload format");
-            queue_->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) payloadType));
+            DEBUG("AudioRtpSession: Setting static payload format");
+            queue_.setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) payloadType));
         }
     }
+}
 
-    if (type_ != Zrtp)
-        ca_->setRecordingSmplRate(getCodecSampleRate());
+void AudioRtpSession::incrementTimestampForDTMF()
+{
+    timestamp_ += timestampIncrement_;
 }
 
 void AudioRtpSession::sendDtmfEvent()
@@ -131,26 +131,26 @@ void AudioRtpSession::sendDtmfEvent()
 
     DEBUG("AudioRtpSession: Send RTP Dtmf (%d)", payload.event);
 
-    timestamp_ += (type_ == Zrtp) ? 160 : timestampIncrement_;
+    incrementTimestampForDTMF();
 
     // discard equivalent size of audio
     processDataEncode();
 
     // change Payload type for DTMF payload
-    queue_->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) getDtmfPayloadType(), 8000));
+    queue_.setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) getDtmfPayloadType(), 8000));
 
-    queue_->setMark(true);
-    queue_->sendImmediate(timestamp_, (const unsigned char *)(&payload), sizeof(payload));
-    queue_->setMark(false);
+    queue_.setMark(true);
+    queue_.sendImmediate(timestamp_, (const unsigned char *)(&payload), sizeof(payload));
+    queue_.setMark(false);
 
     // get back the payload to audio
-    queue_->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) getCodecPayloadType()));
+    queue_.setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) getCodecPayloadType()));
 }
 
 
 void AudioRtpSession::receiveSpeakerData()
 {
-    const ost::AppDataUnit* adu = queue_->getData(queue_->getFirstTimestamp());
+    const ost::AppDataUnit* adu = queue_.getData(queue_.getFirstTimestamp());
 
     if (!adu)
         return;
@@ -166,23 +166,19 @@ void AudioRtpSession::receiveSpeakerData()
 }
 
 
-
 void AudioRtpSession::sendMicData()
 {
     int compSize = processDataEncode();
 
     // if no data return
-    if (!compSize)
+    if (compSize == 0)
         return;
 
     // Increment timestamp for outgoing packet
     timestamp_ += timestampIncrement_;
 
-    if (type_ == Zrtp)
-        queue_->putData(timestamp_, getMicDataEncoded(), compSize);
-
-    // putData put the data on RTP queue, sendImmediate bypass this queue
-    queue_->sendImmediate(timestamp_, getMicDataEncoded(), compSize);
+    // putData puts the data on RTP queue, sendImmediate bypass this queue
+    queue_.sendImmediate(timestamp_, getMicDataEncoded(), compSize);
 }
 
 
@@ -190,28 +186,28 @@ void AudioRtpSession::setSessionTimeouts()
 {
     DEBUG("AudioRtpSession: Set session scheduling timeout (%d) and expireTimeout (%d)", sfl::schedulingTimeout, sfl::expireTimeout);
 
-    queue_->setSchedulingTimeout(sfl::schedulingTimeout);
-    queue_->setExpireTimeout(sfl::expireTimeout);
+    queue_.setSchedulingTimeout(sfl::schedulingTimeout);
+    queue_.setExpireTimeout(sfl::expireTimeout);
 }
 
 void AudioRtpSession::setDestinationIpAddress()
 {
     // Store remote ip in case we would need to forget current destination
-    remote_ip_ = ost::InetHostAddress(ca_->getLocalSDP()->getRemoteIP().c_str());
+    remote_ip_ = ost::InetHostAddress(call_.getLocalSDP()->getRemoteIP().c_str());
 
     if (!remote_ip_) {
         WARN("AudioRtpSession: Target IP address (%s) is not correct!",
-              ca_->getLocalSDP()->getRemoteIP().data());
+              call_.getLocalSDP()->getRemoteIP().data());
         return;
     }
 
     // Store remote port in case we would need to forget current destination
-    remote_port_ = (unsigned short) ca_->getLocalSDP()->getRemoteAudioPort();
+    remote_port_ = (unsigned short) call_.getLocalSDP()->getRemoteAudioPort();
 
     DEBUG("AudioRtpSession: New remote address for session: %s:%d",
-          ca_->getLocalSDP()->getRemoteIP().data(), remote_port_);
+          call_.getLocalSDP()->getRemoteIP().data(), remote_port_);
 
-    if (!queue_->addDestination(remote_ip_, remote_port_)) {
+    if (!queue_.addDestination(remote_ip_, remote_port_)) {
         WARN("AudioRtpSession: Can't add new destination to session!");
         return;
     }
@@ -224,7 +220,7 @@ void AudioRtpSession::updateDestinationIpAddress()
     // Destination address are stored in a list in ccrtp
     // This method remove the current destination entry
 
-    if (!queue_->forgetDestination(remote_ip_, remote_port_, remote_port_ + 1))
+    if (!queue_.forgetDestination(remote_ip_, remote_port_, remote_port_ + 1))
         DEBUG("AudioRtpSession: Did not remove previous destination");
 
     // new destination is stored in call
@@ -233,12 +229,12 @@ void AudioRtpSession::updateDestinationIpAddress()
 }
 
 
-int AudioRtpSession::startRtpThread(AudioCodec* audiocodec)
+int AudioRtpSession::startRtpThread(AudioCodec &audiocodec)
 {
     if (isStarted_)
         return 0;
 
-    DEBUG("AudioSymmetricRtpSession: Starting main thread");
+    DEBUG("AudioRtpSession: Starting main thread");
 
     isStarted_ = true;
     setSessionTimeouts();
@@ -246,16 +242,9 @@ int AudioRtpSession::startRtpThread(AudioCodec* audiocodec)
     initBuffers();
     initNoiseSuppress();
 
-    queue_->enableStack();
-    thread_->start();
-
-    int ret = 0;
-    if (type_ == Zrtp)
-        return ret;
-
-    AudioSymmetricRtpSession *self = dynamic_cast<AudioSymmetricRtpSession*>(this);
-    assert(self);
-    return self->startSymmetricRtpThread();
+    queue_.enableStack();
+    thread_.start();
+    return 0;
 }
 
 
diff --git a/daemon/src/audio/audiortp/audio_rtp_session.h b/daemon/src/audio/audiortp/audio_rtp_session.h
index 4f8723b234f0897490cadd65faa237518d02bbfc..c6baca3f29fd81b9899922e6b1aef87a767a0478 100644
--- a/daemon/src/audio/audiortp/audio_rtp_session.h
+++ b/daemon/src/audio/audiortp/audio_rtp_session.h
@@ -31,44 +31,35 @@
  *  shall include the source code for the parts of OpenSSL used as well
  *  as that of the covered work.
  */
-#ifndef SFL_AUDIO_RTP_SESSION_H_
-#define SFL_AUDIO_RTP_SESSION_H_
+#ifndef AUDIO_RTP_SESSION_H_
+#define AUDIO_RTP_SESSION_H_
 
 #include "audio_rtp_record_handler.h"
-#include <audio/codecs/audiocodec.h>
 #include <ccrtp/rtp.h>
 #include <ccrtp/formats.h>
 #include "noncopyable.h"
 
 class SIPCall;
+namespace ost {
+    class Thread;
+}
 
 namespace sfl {
 
 class AudioCodec;
 
-// Possible kind of rtp session
-typedef enum RtpMethod {
-    Symmetric,
-    Zrtp,
-    Sdes
-} RtpMethod;
-
-
 class AudioRtpSession : public AudioRtpRecordHandler {
     public:
         /**
         * Constructor
         * @param sipcall The pointer on the SIP call
         */
-        AudioRtpSession(SIPCall* sipcall, RtpMethod type, ost::RTPDataQueue *queue, ost::Thread *thread);
+        AudioRtpSession(SIPCall &sipcall, ost::RTPDataQueue &queue, ost::Thread &thread);
         virtual ~AudioRtpSession();
 
-        RtpMethod getAudioRtpType() {
-            return type_;
-        }
-        void updateSessionMedia(AudioCodec *audioCodec);
+        void updateSessionMedia(AudioCodec &audioCodec);
 
-        int startRtpThread(AudioCodec*);
+        virtual int startRtpThread(AudioCodec&);
 
         /**
          * Used mostly when receiving a reinvite
@@ -76,6 +67,11 @@ class AudioRtpSession : public AudioRtpRecordHandler {
         void updateDestinationIpAddress();
 
     protected:
+        /**
+         * Set the audio codec for this RTP session
+         */
+        virtual void setSessionMedia(AudioCodec &codec) = 0;
+
 
         bool onRTPPacketRecv(ost::IncomingRTPPkt&);
 
@@ -90,19 +86,26 @@ class AudioRtpSession : public AudioRtpRecordHandler {
         /**
          * Send encoded data to peer
          */
-        void sendMicData();
-
-        SIPCall *ca_;
+        virtual void sendMicData();
 
-        RtpMethod type_;
+        SIPCall &call_;
 
-    private:
-        NON_COPYABLE(AudioRtpSession);
+        /**
+         * Timestamp for this session
+         */
+        int timestamp_;
 
         /**
-         * Set the audio codec for this RTP session
+         * Timestamp incrementation value based on codec period length (framesize)
+         * except for G722 which require a 8 kHz incrementation.
          */
-        void setSessionMedia(AudioCodec*);
+        int timestampIncrement_;
+
+        ost::RTPDataQueue &queue_;
+
+        bool isStarted_;
+    private:
+        NON_COPYABLE(AudioRtpSession);
 
         /**
          * Set RTP Sockets send/receive timeouts
@@ -119,6 +122,11 @@ class AudioRtpSession : public AudioRtpRecordHandler {
          */
         void receiveSpeakerData();
 
+        /**
+         * Increment timestamp for DTMF event
+         */
+        virtual void incrementTimestampForDTMF();
+
         // Main destination address for this rtp session.
         // Stored in case or reINVITE, which may require to forget
         // this destination and update a new one.
@@ -129,27 +137,12 @@ class AudioRtpSession : public AudioRtpRecordHandler {
         // this destination and update a new one
         unsigned short remote_port_;
 
-        /**
-         * Timestamp for this session
-         */
-        int timestamp_;
-
-        /**
-         * Timestamp incrementation value based on codec period length (framesize)
-         * except for G722 which require a 8 kHz incrementation.
-         */
-        int timestampIncrement_;
-
         /**
          * Timestamp reset frequency specified in number of packet sent
          */
         short timestampCount_;
 
-        bool isStarted_;
-
-        ost::RTPDataQueue *queue_;
-
-        ost::Thread *thread_;
+        ost::Thread &thread_;
 };
 
 }
diff --git a/daemon/src/audio/audiortp/audio_srtp_session.cpp b/daemon/src/audio/audiortp/audio_srtp_session.cpp
index ed8a637fc07953ce9a04e3879bab053b62084f5a..fb14463dbb0983fa9e669a9fb03f4fa2ed6021b8 100644
--- a/daemon/src/audio/audiortp/audio_srtp_session.cpp
+++ b/daemon/src/audio/audiortp/audio_srtp_session.cpp
@@ -29,8 +29,6 @@
  */
 #include "audio_srtp_session.h"
 
-#include "sip/sipcall.h"
-
 #include <openssl/sha.h>
 #include <openssl/hmac.h>
 #include <openssl/evp.h>
@@ -44,10 +42,82 @@
 
 namespace sfl {
 
-AudioSrtpSession::AudioSrtpSession(SIPCall * sipcall) :
-    AudioSymmetricRtpSession(sipcall),
-    remoteCryptoCtx_(NULL),
-    localCryptoCtx_(NULL),
+namespace {
+    std::string
+    encodeBase64(unsigned char *input, int length)
+    {
+        // init decoder
+        BIO *b64 = BIO_new(BIO_f_base64());
+        BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+
+        // init internal buffer
+        BIO *bmem = BIO_new(BIO_s_mem());
+
+        // create decoder chain
+        b64 = BIO_push(b64, bmem);
+
+        BIO_write(b64, input, length);
+        // BIO_flush (b64);
+
+        // get pointer to data
+        BUF_MEM *bptr = 0;
+        BIO_get_mem_ptr(b64, &bptr);
+
+        std::string output(bptr->data, bptr->length);
+
+        BIO_free_all(bmem);
+
+        return output;
+    }
+
+    std::vector<char> decodeBase64(unsigned char *input, int length)
+    {
+        BIO *b64, *bmem;
+
+        // init decoder and read-only BIO buffer
+        b64 = BIO_new(BIO_f_base64());
+        BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+
+        // init internal buffer
+        bmem = BIO_new_mem_buf(input, length);
+
+        // create encoder chain
+        bmem = BIO_push(b64, bmem);
+
+        std::vector<char> buffer(length, 0);
+        BIO_read(bmem, &(*buffer.begin()), length);
+
+        BIO_free_all(bmem);
+
+        return buffer;
+    }
+
+    // Fills the array dest with length random bytes
+    void buffer_fill(unsigned char dest [], size_t length)
+    {
+        DEBUG("AudioSrtp: Init local master key");
+
+        // @TODO key may have different length depending on cipher suite
+        // Allocate memory for key
+        std::vector<unsigned char> random_key(length);
+
+        // Generate ryptographically strong pseudo-random bytes
+        int err;
+
+        if ((err = RAND_bytes(&(*random_key.begin()), length)) != 1)
+            DEBUG("Error occured while generating cryptographically strong pseudo-random key");
+
+        assert((sizeof dest / sizeof dest[0]) <= length);
+        memcpy(dest, &(*random_key.begin()), length);
+    }
+}
+
+
+
+AudioSrtpSession::AudioSrtpSession(SIPCall &call) :
+    AudioSymmetricRtpSession(call),
+    remoteCryptoCtx_(0),
+    localCryptoCtx_(0),
     localCryptoSuite_(0),
     remoteCryptoSuite_(0),
     localMasterKey_(),
@@ -59,16 +129,10 @@ AudioSrtpSession::AudioSrtpSession(SIPCall * sipcall) :
     remoteMasterSalt_(),
     remoteMasterSaltLength_(0),
     remoteOfferIsSet_(false)
-{
-    type_ = Sdes;
-}
+{}
 
-AudioSrtpSession::~AudioSrtpSession()
-{
-    DEBUG("AudioSrtp: Destroy audio srtp session");
-}
 
-void AudioSrtpSession::initLocalCryptoInfo()
+ost::CryptoContext* AudioSrtpSession::initLocalCryptoInfo()
 {
     DEBUG("AudioSrtp: Set cryptographic info for this rtp session");
 
@@ -81,6 +145,7 @@ void AudioSrtpSession::initLocalCryptoInfo()
     localCryptoCtx_->deriveSrtpKeys(0);
 
     setOutQueueCryptoContext(localCryptoCtx_);
+    return localCryptoCtx_;
 }
 
 std::vector<std::string> AudioSrtpSession::getLocalCryptoInfo()
@@ -115,7 +180,8 @@ std::vector<std::string> AudioSrtpSession::getLocalCryptoInfo()
     return crypto_vector;
 }
 
-void AudioSrtpSession::setRemoteCryptoInfo(sfl::SdesNegotiator& nego)
+ost::CryptoContext*
+AudioSrtpSession::setRemoteCryptoInfo(sfl::SdesNegotiator& nego)
 {
     if (not remoteOfferIsSet_) {
         DEBUG("%s", nego.getKeyInfo().c_str());
@@ -134,49 +200,26 @@ void AudioSrtpSession::setRemoteCryptoInfo(sfl::SdesNegotiator& nego)
         initializeRemoteCryptoContext();
         setInQueueCryptoContext(remoteCryptoCtx_);
 
-        // initLocalCryptoInfo();
         remoteOfferIsSet_ = true;
     }
+    return remoteCryptoCtx_;
 }
 
 void AudioSrtpSession::initializeLocalMasterKey()
 {
     DEBUG("AudioSrtp: Init local master key");
-
     // @TODO key may have different length depending on cipher suite
     localMasterKeyLength_ = sfl::CryptoSuites[localCryptoSuite_].masterKeyLength / 8;
-
     DEBUG("AudioSrtp: Local master key length %d", localMasterKeyLength_);
-
-    // Allocate memory for key
-    unsigned char *random_key = new unsigned char[localMasterKeyLength_];
-
-    // Generate ryptographically strong pseudo-random bytes
-    int err;
-
-    if ((err = RAND_bytes(random_key, localMasterKeyLength_)) != 1)
-        DEBUG("Error occured while generating cryptographically strong pseudo-random key");
-
-    memcpy(localMasterKey_, random_key, localMasterKeyLength_);
+    buffer_fill(localMasterKey_, localMasterKeyLength_);
 }
 
 void AudioSrtpSession::initializeLocalMasterSalt()
 {
     // @TODO key may have different length depending on cipher suite
     localMasterSaltLength_ = sfl::CryptoSuites[localCryptoSuite_].masterSaltLength / 8;
-
-    // Allocate memory for key
-    unsigned char *random_key = new unsigned char[localMasterSaltLength_];
-
     DEBUG("AudioSrtp: Local master salt length %d", localMasterSaltLength_);
-
-    // Generate ryptographically strong pseudo-random bytes
-    int err;
-
-    if ((err = RAND_bytes(random_key, localMasterSaltLength_)) != 1)
-        DEBUG("Error occured while generating cryptographically strong pseudo-random key");
-
-    memcpy(localMasterSalt_, random_key, localMasterSaltLength_);
+    buffer_fill(localMasterSalt_, localMasterSaltLength_);
 }
 
 std::string AudioSrtpSession::getBase64ConcatenatedKeys()
@@ -207,13 +250,11 @@ void AudioSrtpSession::unBase64ConcatenatedKeys(std::string base64keys)
     char *dataptr = (char*) base64keys.data();
 
     // decode concatenated binary keys
-    char *output = decodeBase64((unsigned char*) dataptr, strlen(dataptr));
+    std::vector<char> output(decodeBase64((unsigned char*) dataptr, strlen(dataptr)));
 
     // copy master and slt respectively
-    memcpy((void*) remoteMasterKey_, (void*) output, remoteMasterKeyLength_);
-    memcpy((void*) remoteMasterSalt_, (void*)(output + remoteMasterKeyLength_), remoteMasterSaltLength_);
-
-    delete[] output;
+    memcpy((void*) remoteMasterKey_, &(*output.begin()), remoteMasterKeyLength_);
+    memcpy((void*) remoteMasterSalt_, &(*output.begin()) + remoteMasterKeyLength_, remoteMasterSaltLength_);
 }
 
 void AudioSrtpSession::initializeRemoteCryptoContext()
@@ -222,24 +263,20 @@ void AudioSrtpSession::initializeRemoteCryptoContext()
 
     CryptoSuiteDefinition crypto = sfl::CryptoSuites[remoteCryptoSuite_];
 
-    if (remoteCryptoCtx_) {
-        delete remoteCryptoCtx_;
-        remoteCryptoCtx_ = NULL;
-    }
-
+    delete remoteCryptoCtx_;
     remoteCryptoCtx_ = new ost::CryptoContext(0x0,
-            0,                               // roc,
-            0L,                              // keydr,
-            SrtpEncryptionAESCM,             // encryption algo
-            SrtpAuthenticationSha1Hmac,      // authtication algo
-            remoteMasterKey_,
-            remoteMasterKeyLength_,
-            remoteMasterSalt_,
-            remoteMasterSaltLength_,
-            crypto.encryptionKeyLength / 8,
-            crypto.srtpAuthKeyLength / 8,
-            crypto.masterSaltLength / 8,                         // session salt len
-            crypto.srtpAuthTagLength / 8);
+                                              0,    // roc,
+                                              0L,   // keydr,
+                                              SrtpEncryptionAESCM,
+                                              SrtpAuthenticationSha1Hmac,
+                                              remoteMasterKey_,
+                                              remoteMasterKeyLength_,
+                                              remoteMasterSalt_,
+                                              remoteMasterSaltLength_,
+                                              crypto.encryptionKeyLength / 8,
+                                              crypto.srtpAuthKeyLength / 8,
+                                              crypto.masterSaltLength / 8,
+                                              crypto.srtpAuthTagLength / 8);
 
 }
 
@@ -249,81 +286,31 @@ void AudioSrtpSession::initializeLocalCryptoContext()
 
     CryptoSuiteDefinition crypto = sfl::CryptoSuites[localCryptoSuite_];
 
-    if (localCryptoCtx_) {
-        delete localCryptoCtx_;
-        localCryptoCtx_ = NULL;
-    }
-
+    delete localCryptoCtx_;
     localCryptoCtx_ = new ost::CryptoContext(OutgoingDataQueue::getLocalSSRC(),
-            0,                               // roc,
-            0L,                              // keydr,
-            SrtpEncryptionAESCM,             // encryption algo
-            SrtpAuthenticationSha1Hmac,      // authtication algo
-            localMasterKey_,
-            localMasterKeyLength_,
-            localMasterSalt_,
-            localMasterSaltLength_,
-            crypto.encryptionKeyLength / 8,
-            crypto.srtpAuthKeyLength / 8,
-            crypto.masterSaltLength / 8,                         // session salt len
-            crypto.srtpAuthTagLength / 8);
+                                             0,     // roc,
+                                             0L,    // keydr,
+                                             SrtpEncryptionAESCM,
+                                             SrtpAuthenticationSha1Hmac,
+                                             localMasterKey_,
+                                             localMasterKeyLength_,
+                                             localMasterSalt_,
+                                             localMasterSaltLength_,
+                                             crypto.encryptionKeyLength / 8,
+                                             crypto.srtpAuthKeyLength / 8,
+                                             crypto.masterSaltLength / 8,
+                                             crypto.srtpAuthTagLength / 8);
 }
 
-void AudioSrtpSession::restoreCryptoContext(ost::CryptoContext *localContext, ost::CryptoContext *remoteContext)
+void AudioSrtpSession::restoreCryptoContext(ost::CryptoContext *localContext,
+                                            ost::CryptoContext *remoteContext)
 {
-    setInQueueCryptoContext(remoteContext);
-    setOutQueueCryptoContext(localContext);
-}
-
-std::string AudioSrtpSession::encodeBase64(unsigned char *input, int length)
-{
-    BIO *b64, *bmem;
-    BUF_MEM *bptr ;
-
-    // init decoder
-    b64 = BIO_new(BIO_f_base64());
-    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
-
-    // init internal buffer
-    bmem = BIO_new(BIO_s_mem());
-
-    // create decoder chain
-    b64 = BIO_push(b64, bmem);
-
-    BIO_write(b64, input, length);
-    // BIO_flush (b64);
-
-    // get pointer to data
-    BIO_get_mem_ptr(b64, &bptr);
-
-    std::string output(bptr->data, bptr->length);
-
-    BIO_free_all(bmem);
-
-    return output;
+    delete remoteCryptoCtx_;
+    remoteCryptoCtx_ = remoteContext;
+    delete localCryptoCtx_;
+    localCryptoCtx_ = localContext;
+    setInQueueCryptoContext(remoteCryptoCtx_);
+    setOutQueueCryptoContext(localCryptoCtx_);
 }
 
-char* AudioSrtpSession::decodeBase64(unsigned char *input, int length)
-{
-    BIO *b64, *bmem;
-
-    // init decoder and read-only BIO buffer
-    b64 = BIO_new(BIO_f_base64());
-    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
-
-    // init internal buffer
-    bmem = BIO_new_mem_buf(input, length);
-
-    // create encoder chain
-    bmem = BIO_push(b64, bmem);
-
-    char *buffer = new char[length];
-    memset(buffer, 0, length);
-
-    BIO_read(bmem, buffer, length);
-
-    BIO_free_all(bmem);
-
-    return buffer;
-}
 }
diff --git a/daemon/src/audio/audiortp/audio_srtp_session.h b/daemon/src/audio/audiortp/audio_srtp_session.h
index f641e8eaa55b21065e7efcee35eb87f3543f93eb..97b9b2ce675dbd848ea6c76c235a2f50e2e33dc3 100644
--- a/daemon/src/audio/audiortp/audio_srtp_session.h
+++ b/daemon/src/audio/audiortp/audio_srtp_session.h
@@ -27,10 +27,9 @@
  *  shall include the source code for the parts of OpenSSL used as well
  *  as that of the covered work.
  */
-#ifndef __AUDIO_SRTP_SESSION_H__
-#define __AUDIO_SRTP_SESSION_H__
+#ifndef AUDIO_SRTP_SESSION_H_
+#define AUDIO_SRTP_SESSION_H_
 
-#include "audio_rtp_session.h"
 #include "audio_symmetric_rtp_session.h"
 #include "sip/sdes_negotiator.h"
 #include "noncopyable.h"
@@ -73,9 +72,7 @@ class AudioSrtpSession : public AudioSymmetricRtpSession {
         /**
          * Constructor for this rtp session
          */
-        AudioSrtpSession(SIPCall * sipcall);
-
-        ~AudioSrtpSession();
+        AudioSrtpSession(SIPCall &call);
 
         /**
          * Used to get sdp crypto header to be included in sdp session. This
@@ -86,15 +83,17 @@ class AudioSrtpSession : public AudioSymmetricRtpSession {
 
         /**
          * Set remote crypto header from incoming sdp offer
+         * @return The new remote crypto context, to be cached by the caller
          */
-        void setRemoteCryptoInfo(sfl::SdesNegotiator& nego);
+        ost::CryptoContext* setRemoteCryptoInfo(sfl::SdesNegotiator &nego);
 
         /**
          * Init local crypto context for outgoing data
-        * this method must be called before sending first Invite request
-        * with SDP offer.
-        */
-        void initLocalCryptoInfo();
+         * this method must be called before sending first Invite request
+         * with SDP offer.
+         * @return The new local crypto context, to be cached by the caller
+         */
+        ost::CryptoContext* initLocalCryptoInfo();
 
         /**
          * Restore the cryptographic context. most likely useful to restore
@@ -102,6 +101,8 @@ class AudioSrtpSession : public AudioSymmetricRtpSession {
          */
         void restoreCryptoContext(ost::CryptoContext *, ost::CryptoContext *);
 
+    private:
+        NON_COPYABLE(AudioSrtpSession);
 
         /** Remote srtp crypto context to be set into incoming data queue. */
         ost::CryptoContext* remoteCryptoCtx_;
@@ -109,9 +110,6 @@ class AudioSrtpSession : public AudioSymmetricRtpSession {
         /** Local srtp crypto context to be set into outgoing data queue. */
         ost::CryptoContext* localCryptoCtx_;
 
-    private:
-        NON_COPYABLE(AudioSrtpSession);
-
         /**
          * Init local master key according to current crypto context
          * as defined in SdesNegotiator.h
@@ -146,16 +144,6 @@ class AudioSrtpSession : public AudioSymmetricRtpSession {
          */
         void unBase64ConcatenatedKeys(std::string base64keys);
 
-        /**
-         * Encode input data as base64
-         */
-        std::string encodeBase64(unsigned char *input, int length);
-
-        /**
-         * Decode base64 data
-         */
-        char* decodeBase64(unsigned char *input, int length);
-
         /** Default local crypto suite is AES_CM_128_HMAC_SHA1_80*/
         int localCryptoSuite_;
 
diff --git a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp
index a4499aa0310f8755094db80cff3694a3e70c13a2..3324f22ff4358f7713cf8e024decb2eff9f4abc1 100644
--- a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp
+++ b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp
@@ -41,24 +41,25 @@
 
 namespace sfl {
 
-AudioSymmetricRtpSession::AudioSymmetricRtpSession(SIPCall * sipcall) :
+AudioSymmetricRtpSession::AudioSymmetricRtpSession(SIPCall &call) :
     ost::TimerPort()
-    , ost::SymmetricRTPSession(ost::InetHostAddress(sipcall->getLocalIp().c_str()), sipcall->getLocalAudioPort())
-    , AudioRtpSession(sipcall, Symmetric, this, this)
-    , echoCanceller()
-    , rtpThread_(new AudioRtpThread(this))
+    , ost::SymmetricRTPSession(ost::InetHostAddress(call.getLocalIp().c_str()), call.getLocalAudioPort())
+    , AudioRtpSession(call, *this, *this)
+    , rtpThread_(*this)
 {
-    DEBUG("AudioSymmetricRtpSession: Setting new RTP session with destination %s:%d", ca_->getLocalIp().c_str(), ca_->getLocalAudioPort());
-    audioRtpRecord_.callId_ = ca_->getCallId();
+    DEBUG("AudioSymmetricRtpSession: Setting new RTP session with destination %s:%d", call_.getLocalIp().c_str(), call_.getLocalAudioPort());
+    audioRtpRecord_.callId_ = call_.getCallId();
 }
 
 AudioSymmetricRtpSession::~AudioSymmetricRtpSession()
 {
-    rtpThread_->running = false;
-    delete rtpThread_;
+    if (rtpThread_.running_) {
+        rtpThread_.running_ = false;
+        rtpThread_.join();
+    }
 }
 
-AudioSymmetricRtpSession::AudioRtpThread::AudioRtpThread(AudioSymmetricRtpSession *session) : running(true), rtpSession(session)
+AudioSymmetricRtpSession::AudioRtpThread::AudioRtpThread(AudioSymmetricRtpSession &session) : running_(true), rtpSession_(session)
 {}
 
 void AudioSymmetricRtpSession::AudioRtpThread::run()
@@ -69,20 +70,35 @@ void AudioSymmetricRtpSession::AudioRtpThread::run()
 
     DEBUG("AudioRtpThread: Entering Audio rtp thread main loop");
 
-    while (running) {
+    while (running_) {
         // Send session
-        if (rtpSession->DtmfPending())
-            rtpSession->sendDtmfEvent();
+        if (rtpSession_.DtmfPending())
+            rtpSession_.sendDtmfEvent();
         else
-            rtpSession->sendMicData();
+            rtpSession_.sendMicData();
 
         Thread::sleep(TimerPort::getTimer());
 
         TimerPort::incTimer(threadSleep);
-        DEBUG("Main Loop Running");
     }
 
     DEBUG("AudioRtpThread: Leaving audio rtp thread loop");
 }
 
+void AudioSymmetricRtpSession::setSessionMedia(AudioCodec &audioCodec)
+{
+    AudioRtpSession::setSessionMedia(audioCodec);
+    call_.setRecordingSmplRate(getCodecSampleRate());
+}
+
+int AudioSymmetricRtpSession::startRtpThread(AudioCodec &audiocodec)
+{
+    DEBUG("AudioSymmetricRtpSession: Starting main thread");
+    if (isStarted_)
+        return 0;
+
+    AudioRtpSession::startRtpThread(audiocodec);
+    return startSymmetricRtpThread();
+}
+
 }
diff --git a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h
index 7d9fc21b826ac0852d0aadd0ea383fccdb34ea29..c89d39143b9f0412533b4bc6c2f5b1a81ac5bbb7 100644
--- a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h
+++ b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h
@@ -56,10 +56,9 @@ class AudioSymmetricRtpSession : public ost::TimerPort, public ost::SymmetricRTP
     public:
         /**
         * Constructor
-        * @param sipcall The pointer on the SIP call
+        * @param call The SIP call
         */
-        AudioSymmetricRtpSession(SIPCall* sipcall);
-
+        AudioSymmetricRtpSession(SIPCall &call);
         ~AudioSymmetricRtpSession();
 
         virtual bool onRTPPacketRecv(ost::IncomingRTPPkt& pkt) {
@@ -67,8 +66,7 @@ class AudioSymmetricRtpSession : public ost::TimerPort, public ost::SymmetricRTP
         }
 
         int startSymmetricRtpThread() {
-            assert(rtpThread_);
-            rtpThread_->start();
+            rtpThread_.start();
             return 0;
         }
 
@@ -77,21 +75,20 @@ class AudioSymmetricRtpSession : public ost::TimerPort, public ost::SymmetricRTP
 
         class AudioRtpThread : public ost::Thread, public ost::TimerPort {
             public:
-                AudioRtpThread(AudioSymmetricRtpSession *session);
-                ~AudioRtpThread(){}
+                AudioRtpThread(AudioSymmetricRtpSession &session);
 
                 virtual void run();
 
-                bool running;
+                bool running_;
 
             private:
                 NON_COPYABLE(AudioRtpThread);
-                AudioSymmetricRtpSession *rtpSession;
+                AudioSymmetricRtpSession &rtpSession_;
         };
-        SpeexEchoCancel echoCanceller;
+        void setSessionMedia(AudioCodec &codec);
+        int startRtpThread(AudioCodec &audiocodec);
 
-    private:
-        AudioRtpThread *rtpThread_;
+        AudioRtpThread rtpThread_;
 };
 
 }
diff --git a/daemon/src/audio/audiortp/audio_zrtp_session.cpp b/daemon/src/audio/audiortp/audio_zrtp_session.cpp
index 741fe39367d34b52b9fdfa9a820f7d030be23e55..d03767ead8c84cd0abfd9a1c6b58b36bd9f30e18 100644
--- a/daemon/src/audio/audiortp/audio_zrtp_session.cpp
+++ b/daemon/src/audio/audiortp/audio_zrtp_session.cpp
@@ -49,26 +49,27 @@
 
 namespace sfl {
 
-AudioZrtpSession::AudioZrtpSession(SIPCall * sipcall, const std::string& zidFilename) :
-    AudioRtpSession(sipcall, Zrtp, this, this),
-    ost::TRTPSessionBase<ost::SymmetricRTPChannel, ost::SymmetricRTPChannel, ost::ZrtpQueue>(ost::InetHostAddress(sipcall->getLocalIp().c_str()),
-            sipcall->getLocalAudioPort(),
-            0,
-            ost::MembershipBookkeeping::defaultMembersHashSize,
-            ost::defaultApplication()),
+AudioZrtpSession::AudioZrtpSession(SIPCall &call, const std::string& zidFilename) :
+    AudioRtpSession(call, *this, *this),
+    ost::TRTPSessionBase<ost::SymmetricRTPChannel, ost::SymmetricRTPChannel, ost::ZrtpQueue>(ost::InetHostAddress(call_.getLocalIp().c_str()),
+    call_.getLocalAudioPort(),
+    0,
+    ost::MembershipBookkeeping::defaultMembersHashSize,
+    ost::defaultApplication()),
     zidFilename_(zidFilename)
 {
     DEBUG("AudioZrtpSession initialized");
     initializeZid();
 
 
-    DEBUG("AudioZrtpSession: Setting new RTP session with destination %s:%d", ca_->getLocalIp().c_str(), ca_->getLocalAudioPort());
+    DEBUG("AudioZrtpSession: Setting new RTP session with destination %s:%d",
+          call_.getLocalIp().c_str(), call_.getLocalAudioPort());
 }
 
 AudioZrtpSession::~AudioZrtpSession()
 {
     ost::Thread::terminate();
-    Manager::instance().getMainBuffer()->unBindAll(ca_->getCallId());
+    Manager::instance().getMainBuffer()->unBindAll(call_.getCallId());
 }
 
 void AudioZrtpSession::final()
@@ -101,7 +102,7 @@ void AudioZrtpSession::initializeZid()
     if (initialize(zidCompleteFilename.c_str()) >= 0) {
         DEBUG("Register callbacks");
         setEnableZrtp(true);
-        setUserCallback(new ZrtpSessionCallback(ca_));
+        setUserCallback(new ZrtpSessionCallback(call_));
         return;
     }
 
@@ -116,11 +117,29 @@ void AudioZrtpSession::initializeZid()
     return;
 }
 
+void AudioZrtpSession::sendMicData()
+{
+    int compSize = processDataEncode();
+
+    // if no data return
+    if (compSize == 0)
+        return;
+
+    // Increment timestamp for outgoing packet
+    timestamp_ += timestampIncrement_;
+
+    // this step is only needed for ZRTP
+    queue_.putData(timestamp_, getMicDataEncoded(), compSize);
+
+    // putData puts the data on RTP queue, sendImmediate bypasses this queue
+    queue_.sendImmediate(timestamp_, getMicDataEncoded(), compSize);
+}
+
 void AudioZrtpSession::run()
 {
     // Set recording sampling rate
-    ca_->setRecordingSmplRate(getCodecSampleRate());
-    DEBUG("AudioZrtpSession: Entering mainloop for call %s", ca_->getCallId().c_str());
+    call_.setRecordingSmplRate(getCodecSampleRate());
+    DEBUG("AudioZrtpSession: Entering mainloop for call %s", call_.getCallId().c_str());
 
     uint32 timeout = 0;
 
@@ -146,7 +165,8 @@ void AudioZrtpSession::run()
             // dispatchDataPacket();
             timerTick();
         } else {
-            if (isPendingData(timeout/1000)) {
+            if (isPendingData(timeout / 1000)) {
+
                 if (isActive())
                     takeInDataPacket();
             }
@@ -154,6 +174,17 @@ void AudioZrtpSession::run()
         }
     }
 
-    DEBUG("AudioZrtpSession: Left main loop for call %s", ca_->getCallId().c_str());
+    DEBUG("AudioZrtpSession: Left main loop for call %s", call_.getCallId().c_str());
+}
+
+void AudioZrtpSession::incrementTimestampForDTMF()
+{
+    timestamp_ += 160;
+}
+
+void AudioZrtpSession::setSessionMedia(AudioCodec &audioCodec)
+{
+    AudioRtpSession::setSessionMedia(audioCodec);
 }
+
 }
diff --git a/daemon/src/audio/audiortp/audio_zrtp_session.h b/daemon/src/audio/audiortp/audio_zrtp_session.h
index aed4aa79fc4e805cd336bc933a15c280391a6d96..c635349efe74dd3bf11e8100eea34eabd2afa367 100644
--- a/daemon/src/audio/audiortp/audio_zrtp_session.h
+++ b/daemon/src/audio/audiortp/audio_zrtp_session.h
@@ -43,19 +43,21 @@ using std::ptrdiff_t;
 // #include <commoncpp/numbers.h> // OST::Time
 
 class SIPCall;
+class AudioCodec;
 
 namespace sfl {
 
-class ZrtpZidException: public std::runtime_error {
+class ZrtpZidException : public std::runtime_error {
     public:
         ZrtpZidException(const std::string& str = "") :
             std::runtime_error("ZRTP ZID initialization failed." + str) {}
 };
 
-// class AudioZrtpSession : public ost::TimerPort, public ost::SymmetricZRTPSession, public AudioRtpRecordHandler
-class AudioZrtpSession : public AudioRtpSession, protected ost::Thread, public ost::TRTPSessionBase<ost::SymmetricRTPChannel, ost::SymmetricRTPChannel, ost::ZrtpQueue> {
+class AudioZrtpSession :
+    public AudioRtpSession, protected ost::Thread,
+    public ost::TRTPSessionBase<ost::SymmetricRTPChannel, ost::SymmetricRTPChannel, ost::ZrtpQueue> {
     public:
-        AudioZrtpSession(SIPCall * sipcall, const std::string& zidFilename);
+        AudioZrtpSession(SIPCall &call, const std::string& zidFilename);
         ~AudioZrtpSession();
 
         virtual void final();
@@ -63,13 +65,16 @@ class AudioZrtpSession : public AudioRtpSession, protected ost::Thread, public o
         // Thread associated method
         virtual void run();
 
-        virtual bool onRTPPacketRecv(ost::IncomingRTPPkt& pkt) {
+        virtual bool onRTPPacketRecv(ost::IncomingRTPPkt &pkt) {
             return AudioRtpSession::onRTPPacketRecv(pkt);
         }
 
     private:
+        void sendMicData();
         void initializeZid();
         std::string zidFilename_;
+        void incrementTimestampForDTMF();
+        void setSessionMedia(AudioCodec &codec);
 };
 
 }
diff --git a/daemon/src/audio/audiortp/zrtp_session_callback.cpp b/daemon/src/audio/audiortp/zrtp_session_callback.cpp
index 270468a80ea2a8fc8e683d515610d31dce7d0a17..061cf1c64c22b66f270e80302085e149d5328de8 100644
--- a/daemon/src/audio/audiortp/zrtp_session_callback.cpp
+++ b/daemon/src/audio/audiortp/zrtp_session_callback.cpp
@@ -45,8 +45,8 @@ using namespace ost;
 
 namespace sfl {
 
-ZrtpSessionCallback::ZrtpSessionCallback(SIPCall *sipcall) :
-    sipcall_(sipcall)
+ZrtpSessionCallback::ZrtpSessionCallback(SIPCall &call) :
+    call_(call)
 {
     using std::pair;
     using std::string;
@@ -112,21 +112,21 @@ void
 ZrtpSessionCallback::secureOn(std::string cipher)
 {
     DEBUG("Zrtp: Secure mode is on with cipher %s", cipher.c_str());
-    Manager::instance().getDbusManager()->getCallManager()->secureZrtpOn(sipcall_->getCallId(), cipher);
+    Manager::instance().getDbusManager()->getCallManager()->secureZrtpOn(call_.getCallId(), cipher);
 }
 
 void
 ZrtpSessionCallback::secureOff()
 {
     DEBUG("Zrtp: Secure mode is off");
-    Manager::instance().getDbusManager()->getCallManager()->secureZrtpOff(sipcall_->getCallId());
+    Manager::instance().getDbusManager()->getCallManager()->secureZrtpOff(call_.getCallId());
 }
 
 void
 ZrtpSessionCallback::showSAS(std::string sas, bool verified)
 {
     DEBUG("Zrtp: SAS is: %s", sas.c_str());
-    Manager::instance().getDbusManager()->getCallManager()->showSAS(sipcall_->getCallId(), sas, verified);
+    Manager::instance().getDbusManager()->getCallManager()->showSAS(call_.getCallId(), sas, verified);
 }
 
 
@@ -134,7 +134,7 @@ void
 ZrtpSessionCallback::zrtpNotSuppOther()
 {
     DEBUG("Zrtp: Callee does not support ZRTP");
-    Manager::instance().getDbusManager()->getCallManager()->zrtpNotSuppOther(sipcall_->getCallId());
+    Manager::instance().getDbusManager()->getCallManager()->zrtpNotSuppOther(call_.getCallId());
 }
 
 
@@ -163,13 +163,13 @@ ZrtpSessionCallback::zrtpNegotiationFailed(MessageSeverity severity, int subCode
         std::map<int32, std::string>::const_iterator iter = zrtpMap_.find(subCode);
         if (iter != zrtpMap_.end()) {
             DEBUG("%s", iter->second.c_str());
-            Manager::instance().getDbusManager()->getCallManager()->zrtpNegotiationFailed(sipcall_->getCallId(), iter->second, "ZRTP");
+            Manager::instance().getDbusManager()->getCallManager()->zrtpNegotiationFailed(call_.getCallId(), iter->second, "ZRTP");
         }
     } else {
         std::map<int32, std::string>::const_iterator iter = severeMap_.find(subCode);
         if (iter != severeMap_.end()) {
             DEBUG("%s", iter->second.c_str());
-            Manager::instance().getDbusManager()->getCallManager()->zrtpNegotiationFailed(sipcall_->getCallId(), iter->second, "severe");
+            Manager::instance().getDbusManager()->getCallManager()->zrtpNegotiationFailed(call_.getCallId(), iter->second, "severe");
         }
     }
 }
@@ -178,7 +178,7 @@ void
 ZrtpSessionCallback::confirmGoClear()
 {
     DEBUG("Zrtp: Received go clear message. Until confirmation, ZRTP won't send any data");
-    Manager::instance().getDbusManager()->getCallManager()->zrtpNotSuppOther(sipcall_->getCallId());
+    Manager::instance().getDbusManager()->getCallManager()->zrtpNotSuppOther(call_.getCallId());
 }
 
 std::map<int32, std::string> ZrtpSessionCallback::infoMap_;
diff --git a/daemon/src/audio/audiortp/zrtp_session_callback.h b/daemon/src/audio/audiortp/zrtp_session_callback.h
index 08bb9cf4fb4c9bffd2f9fbc49d50520dda88a6c3..e9e92a9c2cda8c02dec10a562bb9831dd410cef4 100644
--- a/daemon/src/audio/audiortp/zrtp_session_callback.h
+++ b/daemon/src/audio/audiortp/zrtp_session_callback.h
@@ -28,8 +28,8 @@
  *  as that of the covered work.
  */
 
-#ifndef __ZRTP_SESSION_CALLBACK_H__
-#define __ZRTP_SESSION_CALLBACK_H__
+#ifndef ZRTP_SESSION_CALLBACK_H_
+#define ZRTP_SESSION_CALLBACK_H_
 #include <cstddef>
 
 using std::ptrdiff_t;
@@ -39,7 +39,6 @@ using std::ptrdiff_t;
 #include <libzrtpcpp/ZrtpUserCallback.h>
 #include <exception>
 #include <map>
-#include "noncopyable.h"
 
 class SIPCall;
 
@@ -47,7 +46,7 @@ namespace sfl {
 
 class ZrtpSessionCallback: public ZrtpUserCallback {
     public:
-        ZrtpSessionCallback(SIPCall *sipcall);
+        ZrtpSessionCallback(SIPCall &call);
 
         void secureOn(std::string cipher);
         void secureOff();
@@ -58,12 +57,11 @@ class ZrtpSessionCallback: public ZrtpUserCallback {
         void confirmGoClear();
 
     private:
-        NON_COPYABLE(ZrtpSessionCallback);
-        SIPCall* sipcall_;
+        SIPCall &call_;
         static std::map<int32, std::string> infoMap_;
         static std::map<int32, std::string> warningMap_;
         static std::map<int32, std::string> severeMap_;
         static std::map<int32, std::string> zrtpMap_;
 };
 }
-#endif // __ZRTP_SESSION_CALLBACK_H__
+#endif // ZRTP_SESSION_CALLBACK_H_
diff --git a/daemon/src/dbus/configurationmanager-introspec.xml b/daemon/src/dbus/configurationmanager-introspec.xml
index 6c8f27da36474bb1c61bd1e1c9fadf826e7131b7..a990a0be463994ea5c61a68778e615f23be1c61c 100644
--- a/daemon/src/dbus/configurationmanager-introspec.xml
+++ b/daemon/src/dbus/configurationmanager-introspec.xml
@@ -447,6 +447,11 @@
        <signal name="accountsChanged" tp:name-for-bindings="accountsChanged">
        </signal>
 
+       <signal name="registrationStateChanged" tp:name-for-bindings="registrationStateChanged">
+           <arg type="s" name="accountID"/>
+           <arg type="i" name="registration_state"/>
+       </signal>
+
        <signal name="stunStatusFailure" tp:name-for_bindings="stunStatusFailure">
            <arg type="s" name="reason">
            </arg>
diff --git a/daemon/src/eventthread.cpp b/daemon/src/eventthread.cpp
index c0865a94fb0270a24ee0d6e02736419238316d1f..b712837fc84aeb7719f78f361165e428a4048cd9 100644
--- a/daemon/src/eventthread.cpp
+++ b/daemon/src/eventthread.cpp
@@ -32,16 +32,11 @@
 #include "voiplink.h"
 
 EventThread::EventThread(VoIPLink *link) : Thread(), link_(link)
-{
-}
-
-EventThread::~EventThread() {
-    ost::Thread::terminate();
-}
+{}
 
 void EventThread::run()
 {
-    while (1)
+    while (isRunning())
         link_->getEvent();
 }
 
diff --git a/daemon/src/eventthread.h b/daemon/src/eventthread.h
index f3c04963e7f7994e9718ce844aca9f9116eea151..58676b9f5350c73ab6a12b06ca9471e56d083abf 100644
--- a/daemon/src/eventthread.h
+++ b/daemon/src/eventthread.h
@@ -44,7 +44,6 @@ class VoIPLink;
 class EventThread : public ost::Thread {
     public:
         EventThread(VoIPLink* link);
-        ~EventThread();
         virtual void run();
 
     private:
diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp
index a22b5c698923376a7a8c2a7cad2a3641a8e25b2d..04428236e551c2c7741daee7509bd4fd264b5533 100644
--- a/daemon/src/managerimpl.cpp
+++ b/daemon/src/managerimpl.cpp
@@ -1628,11 +1628,6 @@ void ManagerImpl::startVoiceMessageNotification(const std::string& accountId,
     dbus_.getCallManager()->voiceMailNotify(accountId, nb_msg);
 }
 
-void ManagerImpl::connectionStatusNotification()
-{
-    dbus_.getConfigurationManager()->accountsChanged();
-}
-
 /**
  * Multi Thread
  */
diff --git a/daemon/src/managerimpl.h b/daemon/src/managerimpl.h
index c26160d306e9b244e3aaa58e533af43ffd6127d6..2fd9665b92353b8e52916757113beafc14ba9935 100644
--- a/daemon/src/managerimpl.h
+++ b/daemon/src/managerimpl.h
@@ -399,11 +399,6 @@ class ManagerImpl {
          */
         void startVoiceMessageNotification(const std::string& accountId, int nb_msg);
 
-        /**
-         * Notify the client through DBus that registration state has been updated
-         */
-        void connectionStatusNotification();
-
         /**
          * ConfigurationManager - Send registration request
          * @param accountId The account to register/unregister
diff --git a/daemon/src/sip/sdes_negotiator.h b/daemon/src/sip/sdes_negotiator.h
index 7fb4213555d670af6bd32f68073584107a886c09..416f940b011eecd97d00e196a44e07cb146e688f 100644
--- a/daemon/src/sip/sdes_negotiator.h
+++ b/daemon/src/sip/sdes_negotiator.h
@@ -80,7 +80,7 @@ struct CryptoSuiteDefinition {
 * List of accepted Crypto-Suites
 * as defined in RFC4568 (6.2)
 */
-const CryptoSuiteDefinition CryptoSuites[3] = {
+static const CryptoSuiteDefinition CryptoSuites[] = {
     { (char*) "AES_CM_128_HMAC_SHA1_80", 128, 112, 48, 31, AESCounterMode, 128, HMACSHA1, 80, 80, 160, 160 },
     { (char*) "AES_CM_128_HMAC_SHA1_32", 128, 112, 48, 31, AESCounterMode, 128, HMACSHA1, 32, 80, 160, 160 },
     { (char*) "F8_128_HMAC_SHA1_80", 128, 112, 48, 31, AESF8Mode, 128, HMACSHA1, 80, 80, 160, 160 }
diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp
index a59aaf39e0f02489bc39a45cfc3d05b0ee4567a1..404622ae49d565599f55295db136988f017bf986 100644
--- a/daemon/src/sip/sipaccount.cpp
+++ b/daemon/src/sip/sipaccount.cpp
@@ -607,7 +607,7 @@ void SIPAccount::startKeepAliveTimer() {
         keepAliveDelay_.sec = 60;
     }
     else {
-        DEBUG("Regsitration Expire == %d", registrationExpire_);
+        DEBUG("Registration Expire == %d", registrationExpire_);
         keepAliveDelay_.sec = registrationExpire_;
     }
 
diff --git a/daemon/src/sip/siptransport.cpp b/daemon/src/sip/siptransport.cpp
index 6ce022bc8e293488a0605246654520c0a8f8d09c..b08f7c3017194152235fe28b765eb147d38e504a 100644
--- a/daemon/src/sip/siptransport.cpp
+++ b/daemon/src/sip/siptransport.cpp
@@ -43,7 +43,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
-// #include <linux/if.h>
+#include <unistd.h>
 #include <arpa/inet.h>
 
 #include "siptransport.h"
@@ -373,28 +373,21 @@ void SipTransport::createDefaultSipUdpTransport()
     localUDPTransport_ = account->transport_;
 }
 
-
-pjsip_transport *SipTransport::createUdpTransport(std::string interface, unsigned int port)
+pjsip_transport *
+SipTransport::createUdpTransport(const std::string &interface, unsigned int port)
 {
     // init socket to bind this transport to
-    pj_sockaddr_in bound_addr;
-    pj_bzero(&bound_addr, sizeof(bound_addr));
     pj_uint16_t listeningPort = (pj_uint16_t) port;
-    bound_addr.sin_port = pj_htons(listeningPort);
-    bound_addr.sin_family = PJ_AF_INET;
 
     DEBUG("SipTransport: Create UDP transport on %s:%d", interface.c_str(), port);
 
     // determine the ip address for this transport
     static const char * const DEFAULT_INTERFACE = "default";
     std::string listeningAddress;
-    if (interface == DEFAULT_INTERFACE) {
+    if (interface == DEFAULT_INTERFACE)
         listeningAddress = getSIPLocalIP();
-        bound_addr.sin_addr.s_addr = pj_htonl(PJ_INADDR_ANY);
-    } else {
+    else
         listeningAddress = getInterfaceAddrFromName(interface);
-        bound_addr.sin_addr = pj_inet_addr2(listeningAddress.c_str());
-    }
 
     if (listeningAddress.empty()) {
         ERROR("SipTransport: Could not determine ip address for this transport");
@@ -406,20 +399,27 @@ pjsip_transport *SipTransport::createUdpTransport(std::string interface, unsigne
         return NULL;
     }
 
-    DEBUG("SipTransport: Listening address %s, listening port %d", listeningAddress.c_str(), listeningPort);
-    // The published address for this transport
-    const pjsip_host_port a_name = {
-        pj_str((char*) listeningAddress.c_str()),
-        listeningPort
-    };
-
+    pj_sockaddr boundAddr;
+    pj_str_t udpString;
+    pj_cstr(&udpString, listeningAddress.c_str());
+    pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &udpString, &boundAddr);
+    pj_status_t status;
     pjsip_transport *transport = NULL;
-    pj_status_t status = pjsip_udp_transport_start(endpt_, &bound_addr, &a_name, 1, &transport);
-    if (status != PJ_SUCCESS) {
-        ERROR("SipTransport: Could not create UDP transport for port %u", port);
-        return NULL;
+    if (boundAddr.addr.sa_family == pj_AF_INET()) {
+        status = pjsip_udp_transport_start(endpt_, &boundAddr.ipv4, NULL, 1, &transport);
+        if (status != PJ_SUCCESS) {
+            ERROR("Failed to create IPv4 UDP transport");
+            return NULL;
+        }
+    } else if (boundAddr.addr.sa_family == pj_AF_INET6()) {
+        status = pjsip_udp_transport_start6(endpt_, &boundAddr.ipv6, NULL, 1, &transport);
+        if (status != PJ_SUCCESS) {
+            ERROR("Failed to create IPv6 UDP transport");
+            return NULL;
+        }
     }
 
+    DEBUG("SipTransport: Listening address %s, listening port %d", listeningAddress.c_str(), listeningPort);
     // dump debug information to stdout
     pjsip_tpmgr_dump_transports(pjsip_endpt_get_tpmgr(endpt_));
     transportMap_[listeningPort] = transport;
diff --git a/daemon/src/sip/siptransport.h b/daemon/src/sip/siptransport.h
index 5928a2200f74c84f979a3bae15f6ba26a05878d2..21e2c8780157f153f81f01f5357afca75a97a0fd 100644
--- a/daemon/src/sip/siptransport.h
+++ b/daemon/src/sip/siptransport.h
@@ -117,7 +117,8 @@ class SipTransport {
         * Create SIP UDP transport from account's setting
         * @param account The account for which a transport must be created.
         */
-        pjsip_transport *createUdpTransport(std::string interface, unsigned int port);
+        pjsip_transport *createUdpTransport(const std::string &interface,
+                                            unsigned int port);
 
         /**
          * Initialize the transport selector
diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp
index af567807b57bc5bd76ca85bd38c741acc3a2e493..34003068e50a1da008f3e724953c5b54870b28c8 100644
--- a/daemon/src/sip/sipvoiplink.cpp
+++ b/daemon/src/sip/sipvoiplink.cpp
@@ -318,8 +318,8 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata)
 
     call->getLocalSDP()->setLocalIP(addrSdp);
 
-    call->getAudioRtp().initAudioRtpConfig();
-    call->getAudioRtp().initAudioSymmetricRtpSession();
+    call->getAudioRtp().initConfig();
+    call->getAudioRtp().initSession();
 
     if (rdata->msg_info.msg->body) {
         char sdpbuffer[1000];
@@ -336,7 +336,7 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata)
             CryptoOffer crypto_offer;
             crypto_offer.push_back(std::string(sdpoffer.substr(start, (sdpoffer.size() - start) - 1)));
 
-            std::vector<sfl::CryptoSuiteDefinition>localCapabilities;
+            std::vector<sfl::CryptoSuiteDefinition> localCapabilities;
 
             for (int i = 0; i < 3; i++)
                 localCapabilities.push_back(sfl::CryptoSuites[i]);
@@ -409,7 +409,7 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata)
 
 /*************************************************************************************************/
 
-SIPVoIPLink::SIPVoIPLink() : sipTransport(endpt_, cp_, pool_), evThread_(new EventThread(this))
+SIPVoIPLink::SIPVoIPLink() : sipTransport(endpt_, cp_, pool_), evThread_(this)
 {
 #define TRY(ret) do { \
     if (ret != PJ_SUCCESS) \
@@ -481,12 +481,13 @@ SIPVoIPLink::SIPVoIPLink() : sipTransport(endpt_, cp_, pool_), evThread_(new Eve
     TRY(pjsip_replaces_init_module(endpt_));
 #undef TRY
 
-    evThread_->start();
+    evThread_.detach();
 }
 
 SIPVoIPLink::~SIPVoIPLink()
 {
-    delete evThread_;
+    if (evThread_.isRunning())
+        evThread_.join();
     pj_thread_join(thread);
     pj_thread_destroy(thread);
 
@@ -695,8 +696,8 @@ Call *SIPVoIPLink::newOutgoingCall(const std::string& id, const std::string& toU
     }
 
     try {
-        call->getAudioRtp().initAudioRtpConfig();
-        call->getAudioRtp().initAudioSymmetricRtpSession();
+        call->getAudioRtp().initConfig();
+        call->getAudioRtp().initSession();
         call->getAudioRtp().initLocalCryptoInfo();
         call->getAudioRtp().start(static_cast<sfl::AudioCodec *>(audiocodec));
     } catch (...) {
@@ -830,8 +831,8 @@ SIPVoIPLink::offhold(const std::string& id)
         if (audiocodec == NULL)
             throw VoipLinkException("Could not instantiate codec");
 
-        call->getAudioRtp().initAudioRtpConfig();
-        call->getAudioRtp().initAudioSymmetricRtpSession();
+        call->getAudioRtp().initConfig();
+        call->getAudioRtp().initSession();
         call->getAudioRtp().start(static_cast<sfl::AudioCodec *>(audiocodec));
     } catch (const SdpException &e) {
         ERROR("UserAgent: Exception: %s", e.what());
@@ -1164,8 +1165,8 @@ bool SIPVoIPLink::SIPNewIpToIpCall(const std::string& id, const std::string& to)
 
     // Audio Rtp Session must be initialized before creating initial offer in SDP session
     // since SDES require crypto attribute.
-    call->getAudioRtp().initAudioRtpConfig();
-    call->getAudioRtp().initAudioSymmetricRtpSession();
+    call->getAudioRtp().initConfig();
+    call->getAudioRtp().initSession();
     call->getAudioRtp().initLocalCryptoInfo();
     call->getAudioRtp().start(static_cast<sfl::AudioCodec *>(audiocodec));
 
@@ -1412,7 +1413,7 @@ void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status)
         std::string accountID = Manager::instance().getAccountFromCall(call->getCallId());
 
         if (dynamic_cast<SIPAccount*>(Manager::instance().getAccount(accountID))->getSrtpFallback())
-            call->getAudioRtp().initAudioSymmetricRtpSession();
+            call->getAudioRtp().initSession();
     }
 
     if (!sdpSession)
diff --git a/daemon/src/sip/sipvoiplink.h b/daemon/src/sip/sipvoiplink.h
index c7f65aa731a21aa24c249ee1c0d7e7b4fe817e58..dd2701075c70cd2c7a2efa4cc42da905e62e88ec 100644
--- a/daemon/src/sip/sipvoiplink.h
+++ b/daemon/src/sip/sipvoiplink.h
@@ -46,7 +46,7 @@
 #include <pjnath.h>
 #include <pjnath/stun_config.h>
 ///////////////////////////////
-
+#include "eventthread.h"
 #include "sipaccount.h"
 #include "voiplink.h"
 #include "siptransport.h"
@@ -246,7 +246,7 @@ class SIPVoIPLink : public VoIPLink {
         /**
          * Threading object
          */
-        EventThread *evThread_;
+        EventThread evThread_;
 
         friend class SIPTest;
 };
diff --git a/daemon/test/sflphoned-sample.yml b/daemon/test/sflphoned-sample.yml
index 942b1541229737aa284302e7a7c0239b30c02b2f..3bac267c832a84b794e539dc90e7fa26c9550b35 100644
--- a/daemon/test/sflphoned-sample.yml
+++ b/daemon/test/sflphoned-sample.yml
@@ -1,5 +1,54 @@
 ---
 accounts:
+- alias: SFL test
+  codecs: 0/3/8/9/110/111/112/
+  credential:
+  - Account.password: 1234
+    Account.realm:
+    Account.username: sfltest
+  displayName:
+  dtmfType: overrtp
+  enable: false
+  hostname: localhost
+  id: Account:1334389473
+  interface: default
+  mailbox:
+  port: 5060
+  publishAddr: 0.0.0.0
+  publishPort: 5060
+  registrationexpire: 600
+  ringtoneEnabled: true
+  ringtonePath: /usr/share/sflphone/ringtones/konga.ul
+  sameasLocal: true
+  serviceRoute:
+  srtp:
+    enable: false
+    keyExchange:
+    rtpFallback: false
+  stunEnabled: false
+  stunServer: stun.sflphone.org
+  tls:
+    calist:
+    certificate:
+    ciphers:
+    enable: false
+    method: TLSv1
+    password:
+    privateKey:
+    requireCertif: true
+    server:
+    timeout: 2
+    tlsPort: 5061
+    verifyClient: true
+    verifyServer: true
+  type: SIP
+  updateContact: false
+  username: sfltest
+  zrtp:
+    displaySas: true
+    displaySasOnce: false
+    helloHashEnabled: true
+    notSuppWarning: true
 - alias:
   codecs: 0/
   credential:
diff --git a/gnome/src/accountlist.c b/gnome/src/accountlist.c
index 44c79b011b3ea89f57d8a02f8c87c193c9500de5..91b649826b84b6265244fc50a6763472fbb780c7 100644
--- a/gnome/src/accountlist.c
+++ b/gnome/src/accountlist.c
@@ -33,6 +33,7 @@
 #include "str_utils.h"
 #include "dbus.h"
 #include "accountlist.h"
+#include "logger.h"
 #include "actions.h"
 #include "unused.h"
 
@@ -75,6 +76,7 @@ static gint get_state_struct(gconstpointer a, gconstpointer b)
 
 void account_list_init()
 {
+    account_list_free();
     accountQueue = g_queue_new();
 }
 
@@ -98,6 +100,7 @@ account_list_get_by_state(account_state_t state)
 account_t *
 account_list_get_by_id(const gchar * const accountID)
 {
+    g_assert(accountID);
     GList * c = g_queue_find_custom(accountQueue, accountID, is_accountID_struct);
 
     if (c)
@@ -125,9 +128,7 @@ account_list_get_current()
 
     // if we are here, it means that we have at least one registered account in the list
     // So we get the first one
-    account_t *current = account_list_get_by_state(ACCOUNT_STATE_REGISTERED);
-
-    return current;
+    return account_list_get_by_state(ACCOUNT_STATE_REGISTERED);
 }
 
 void account_list_set_current(account_t *current)
@@ -146,45 +147,30 @@ void account_list_set_current(account_t *current)
 
 const gchar * account_state_name(account_state_t s)
 {
-    gchar * state;
-
     switch (s) {
         case ACCOUNT_STATE_REGISTERED:
-            state = _("Registered");
-            break;
+            return _("Registered");
         case ACCOUNT_STATE_UNREGISTERED:
-            state = _("Not Registered");
-            break;
+            return _("Not Registered");
         case ACCOUNT_STATE_TRYING:
-            state = _("Trying...");
-            break;
+            return _("Trying...");
         case ACCOUNT_STATE_ERROR:
-            state = _("Error");
-            break;
+            return _("Error");
         case ACCOUNT_STATE_ERROR_AUTH:
-            state = _("Authentication Failed");
-            break;
+            return _("Authentication Failed");
         case ACCOUNT_STATE_ERROR_NETWORK:
-            state = _("Network unreachable");
-            break;
+            return _("Network unreachable");
         case ACCOUNT_STATE_ERROR_HOST:
-            state = _("Host unreachable");
-            break;
+            return _("Host unreachable");
         case ACCOUNT_STATE_ERROR_CONF_STUN:
-            state = _("Stun configuration error");
-            break;
+            return _("Stun configuration error");
         case ACCOUNT_STATE_ERROR_EXIST_STUN:
-            state = _("Stun server invalid");
-            break;
-        case IP2IP_PROFILE_STATUS:
-            state = _("Ready");
-            break;
+            return _("Stun server invalid");
+        case ACCOUNT_STATE_IP2IP_READY:
+            return _("Ready");
         default:
-            state = _("Invalid");
-            break;
+            return _("Invalid");
     }
-
-    return state;
 }
 
 void account_list_free_elm(gpointer elm, gpointer data UNUSED)
@@ -197,8 +183,11 @@ void account_list_free_elm(gpointer elm, gpointer data UNUSED)
 
 void account_list_free()
 {
-    g_queue_foreach(accountQueue, account_list_free_elm, NULL);
-    g_queue_free(accountQueue);
+    if (accountQueue) {
+        g_queue_foreach(accountQueue, account_list_free_elm, NULL);
+        g_queue_free(accountQueue);
+        accountQueue = NULL;
+    }
 }
 
 void
@@ -225,7 +214,7 @@ account_list_get_registered_accounts(void)
     guint res = 0;
 
     for (guint i = 0; i < account_list_get_size(); i++)
-        if (account_list_get_nth(i) -> state == (ACCOUNT_STATE_REGISTERED))
+        if (account_list_get_nth(i)->state == (ACCOUNT_STATE_REGISTERED))
             res++;
 
     return res;
@@ -241,6 +230,20 @@ const gchar* account_list_get_current_id(void)
         return NULL;
 }
 
+void account_list_remove(const gchar *accountID)
+{
+    account_t *target = account_list_get_by_id(accountID);
+    if (target) {
+#if GLIB_CHECK_VERSION(2, 30, 0)
+        if (!g_queue_remove(accountQueue, target))
+            ERROR("Could not remove account with ID %s", accountID);
+#else
+        g_queue_remove(accountQueue, target);
+#endif
+    }
+
+}
+
 gchar * account_list_get_ordered_list(void)
 {
     gchar *order = strdup("");
@@ -298,7 +301,7 @@ gboolean current_account_has_new_message(void)
 gboolean account_is_IP2IP(const account_t *account)
 {
     g_assert(account);
-    return g_strcmp0(account->accountID, IP2IP_PROFILE);
+    return g_strcmp0(account->accountID, IP2IP_PROFILE) == 0;
 }
 
 static gboolean is_type(const account_t *account, const gchar *type)
@@ -320,10 +323,20 @@ gboolean account_is_IAX(const account_t *account)
 account_t *create_default_account()
 {
     account_t *account = g_new0(account_t, 1);
-    account->properties = dbus_get_account_details(NULL);
-    account->accountID = g_strdup("new"); //FIXME : replace with NULL for new accounts
-    account->credential_information = NULL;
+    account->accountID = g_strdup("new"); // FIXME: maybe replace with NULL?
+    account->properties = dbus_get_account_details("");
+    sflphone_fill_codec_list_per_account(account);
+    initialize_credential_information(account);
+    return account;
+}
+
+account_t *create_account_with_ID(const gchar *ID)
+{
+    account_t *account = g_new0(account_t, 1);
+    account->accountID = g_strdup(ID);
+    account->properties = dbus_get_account_details(ID);
     sflphone_fill_codec_list_per_account(account);
+    initialize_credential_information(account);
     return account;
 }
 
@@ -341,16 +354,18 @@ void initialize_credential_information(account_t *account)
 
 void account_replace(account_t *account, const gchar *key, const gchar *value)
 {
+    g_assert(account && account->properties);
     g_hash_table_replace(account->properties, g_strdup(key), g_strdup(value));
 }
 
 void account_insert(account_t *account, const gchar *key, const gchar *value)
 {
+    g_assert(account && account->properties);
     g_hash_table_insert(account->properties, g_strdup(key), g_strdup(value));
 }
 
 gpointer account_lookup(const account_t *account, gconstpointer key)
 {
-    g_assert(account->properties);
+    g_assert(account && account->properties);
     return g_hash_table_lookup(account->properties, key);
 }
diff --git a/gnome/src/accountlist.h b/gnome/src/accountlist.h
index 8665e570b1ddfab4519de8157fc01cb33897c897..08d8ef917701b2b57c462358724a6a8363ab5491 100644
--- a/gnome/src/accountlist.h
+++ b/gnome/src/accountlist.h
@@ -29,8 +29,8 @@
  *  as that of the covered work.
  */
 
-#ifndef __ACCOUNTLIST_H__
-#define __ACCOUNTLIST_H__
+#ifndef ACCOUNTLIST_H__
+#define ACCOUNTLIST_H__
 
 #include <gtk/gtk.h>
 /** @file accountlist.h
@@ -41,14 +41,12 @@
   * This enum have all the states an account can take.
   */
 typedef enum {
-    /** Invalid state */
-    ACCOUNT_STATE_INVALID = 0,
-    /** The account is registered  */
-    ACCOUNT_STATE_REGISTERED,
     /** The account is not registered */
     ACCOUNT_STATE_UNREGISTERED,
     /** The account is trying to register */
     ACCOUNT_STATE_TRYING,
+    /** The account is registered  */
+    ACCOUNT_STATE_REGISTERED,
     /** Error state. The account is not registered */
     ACCOUNT_STATE_ERROR,
     /** An authentification error occured. Wrong password or wrong username. The account is not registered */
@@ -57,12 +55,14 @@ typedef enum {
     ACCOUNT_STATE_ERROR_NETWORK,
     /** Host is unreachable. The account is not registered */
     ACCOUNT_STATE_ERROR_HOST,
-    /** Stun server configuration error. The account is not registered */
-    ACCOUNT_STATE_ERROR_CONF_STUN,
     /** Stun server is not existing. The account is not registered */
     ACCOUNT_STATE_ERROR_EXIST_STUN,
-    /** IP profile status **/
-    IP2IP_PROFILE_STATUS
+    /** Stun server configuration error. The account is not registered */
+    ACCOUNT_STATE_ERROR_CONF_STUN,
+    /** IP2IP Account is always ready */
+    ACCOUNT_STATE_IP2IP_READY,
+    /** Invalid state */
+    ACCOUNT_STATE_INVALID
 } account_state_t;
 
 /** @struct account_t
@@ -188,11 +188,13 @@ gboolean account_is_SIP(const account_t *account);
 gboolean account_is_IAX(const account_t *account);
 
 account_t *create_default_account();
+account_t *create_account_with_ID(const gchar *ID);
 
 void initialize_credential_information(account_t *account);
 
 void account_replace(account_t *account, const gchar *key, const gchar *value);
 void account_insert(account_t *account, const gchar *key, const gchar *value);
 gpointer account_lookup(const account_t *account, gconstpointer key);
+void account_list_remove(const gchar *accountID);
 
 #endif
diff --git a/gnome/src/actions.c b/gnome/src/actions.c
index fb385e924b89e61acb7a0173e98d0ff23fda31ad..d74a3987709ab3454eba7e42acdbe1798c7ae472 100644
--- a/gnome/src/actions.c
+++ b/gnome/src/actions.c
@@ -78,7 +78,8 @@ sflphone_notify_voice_mail(const gchar* accountID , guint count)
 
     DEBUG("sflphone_notify_voice_mail begin");
 
-    if (g_ascii_strcasecmp(id, current_id) != 0 || account_list_get_size() == 0)
+    if (g_ascii_strcasecmp(id, current_id) != 0 ||
+        account_list_get_size() == 0)
         return;
 
     // Set the number of voice messages for the current account
@@ -121,18 +122,17 @@ static gboolean is_direct_call(callable_obj_t * c)
 void
 status_bar_display_account()
 {
-    gchar* msg;
-
     statusbar_pop_message(__MSG_ACCOUNT_DEFAULT);
 
     account_t *acc = account_list_get_current();
     status_tray_icon_online(acc != NULL);
 
+    gchar* msg;
     if (acc) {
         msg = g_markup_printf_escaped("%s %s (%s)" ,
                                       _("Using account"),
-                                      (gchar*) g_hash_table_lookup(acc->properties, ACCOUNT_ALIAS),
-                                      (gchar*) g_hash_table_lookup(acc->properties, ACCOUNT_TYPE));
+                                      (gchar*) account_lookup(acc, ACCOUNT_ALIAS),
+                                      (gchar*) account_lookup(acc, ACCOUNT_TYPE));
     } else {
         msg = g_markup_printf_escaped(_("No registered accounts"));
     }
@@ -202,85 +202,56 @@ sflphone_hung_up(callable_obj_t * c)
     statusbar_update_clock("");
 }
 
-/** Internal to actions: Fill account list */
 void sflphone_fill_account_list(void)
 {
-    int count = current_account_get_message_number();
-
-    account_list_free();
     account_list_init();
-
     gchar **array = dbus_account_list();
 
-    if (array) {
-        for (gchar **accountID = array; accountID && *accountID; accountID++) {
-            account_t * a = g_new0(account_t, 1);
-            a->accountID = g_strdup(*accountID);
-            a->credential_information = NULL;
-            account_list_add(a);
-        }
-
-        g_strfreev(array);
-    }
-
-    for (unsigned i = 0; i < account_list_get_size(); i++) {
-        account_t  * a = account_list_get_nth(i);
-
-        if (a == NULL) {
-            ERROR("SFLphone: Error: Could not find account %d in list", i);
+    for (gchar **accountID = array; accountID && *accountID; ++accountID) {
+        account_t *acc = create_account_with_ID(*accountID);
+        if (acc->properties == NULL) {
+            ERROR("SFLphone: Error: Could not fetch details for account %s",
+                  accountID);
             break;
         }
-
-        GHashTable * details = (GHashTable *) dbus_get_account_details(a->accountID);
-
-        if (details == NULL) {
-            ERROR("SFLphone: Error: Could not fetch detais for account %s", a->accountID);
-            break;
-        }
-
-        a->properties = details;
-
+        account_list_add(acc);
         /* Fill the actual array of credentials */
-        dbus_get_credentials(a);
-
-        gchar * status = g_hash_table_lookup(details, REGISTRATION_STATUS);
+        dbus_get_credentials(acc);
+        gchar * status = account_lookup(acc, REGISTRATION_STATUS);
 
         if (g_strcmp0(status, "REGISTERED") == 0)
-            a->state = ACCOUNT_STATE_REGISTERED;
+            acc->state = ACCOUNT_STATE_REGISTERED;
         else if (g_strcmp0(status, "UNREGISTERED") == 0)
-            a->state = ACCOUNT_STATE_UNREGISTERED;
+            acc->state = ACCOUNT_STATE_UNREGISTERED;
         else if (g_strcmp0(status, "TRYING") == 0)
-            a->state = ACCOUNT_STATE_TRYING;
+            acc->state = ACCOUNT_STATE_TRYING;
         else if (g_strcmp0(status, "ERROR") == 0)
-            a->state = ACCOUNT_STATE_ERROR;
+            acc->state = ACCOUNT_STATE_ERROR;
         else if (g_strcmp0(status , "ERROR_AUTH") == 0)
-            a->state = ACCOUNT_STATE_ERROR_AUTH;
+            acc->state = ACCOUNT_STATE_ERROR_AUTH;
         else if (g_strcmp0(status , "ERROR_NETWORK") == 0)
-            a->state = ACCOUNT_STATE_ERROR_NETWORK;
+            acc->state = ACCOUNT_STATE_ERROR_NETWORK;
         else if (g_strcmp0(status , "ERROR_HOST") == 0)
-            a->state = ACCOUNT_STATE_ERROR_HOST;
+            acc->state = ACCOUNT_STATE_ERROR_HOST;
         else if (g_strcmp0(status , "ERROR_CONF_STUN") == 0)
-            a->state = ACCOUNT_STATE_ERROR_CONF_STUN;
+            acc->state = ACCOUNT_STATE_ERROR_CONF_STUN;
         else if (g_strcmp0(status , "ERROR_EXIST_STUN") == 0)
-            a->state = ACCOUNT_STATE_ERROR_EXIST_STUN;
-        else if (g_strcmp0(status, "READY") == 0)
-            a->state = IP2IP_PROFILE_STATUS;
+            acc->state = ACCOUNT_STATE_ERROR_EXIST_STUN;
+        else if (g_strcmp0(status , "ACCOUNT_STATE_IP2IP_READY") == 0)
+            acc->state = ACCOUNT_STATE_IP2IP_READY;
         else
-            a->state = ACCOUNT_STATE_INVALID;
-
-        gchar * code = g_hash_table_lookup(details, REGISTRATION_STATE_CODE);
+            acc->state = ACCOUNT_STATE_INVALID;
 
+        gchar * code = account_lookup(acc, REGISTRATION_STATE_CODE);
         if (code != NULL)
-            a->protocol_state_code = atoi(code);
-
-        g_free(a->protocol_state_description);
-        a->protocol_state_description = g_hash_table_lookup(details, REGISTRATION_STATE_DESCRIPTION);
+            acc->protocol_state_code = atoi(code);
+        acc->protocol_state_description = account_lookup(acc, REGISTRATION_STATE_DESCRIPTION);
     }
 
-    // Set the current account message number
-    current_account_set_message_number(count);
+    g_strfreev(array);
 
-    sflphone_fill_codec_list();
+    // Set the current account message number
+    current_account_set_message_number(current_account_get_message_number());
 }
 
 gboolean sflphone_init(GError **error)
@@ -297,7 +268,6 @@ gboolean sflphone_init(GError **error)
     contacts_tab = calltab_init(TRUE, CONTACTS);
     history_tab = calltab_init(TRUE, HISTORY);
 
-    account_list_init();
     codec_capabilities_load();
     conferencelist_init(current_calls_tab);
 
@@ -965,22 +935,9 @@ sflphone_mute_call()
     toggle_slider_mute_microphone();
 }
 
-void sflphone_fill_codec_list()
-{
-    guint account_list_size = account_list_get_size();
-
-    for (guint i = 0; i < account_list_size; i++) {
-        account_t *current = account_list_get_nth(i);
-
-        if (current)
-            sflphone_fill_codec_list_per_account(current);
-    }
-}
-
 void sflphone_fill_codec_list_per_account(account_t *account)
 {
     GArray *order = dbus_get_active_audio_codec_list(account->accountID);
-
     GQueue *codeclist = account->codecs;
 
     // First clean the list
diff --git a/gnome/src/actions.h b/gnome/src/actions.h
index 145ba402505d43bfdbfa9c2c7a424af1e0cca032..4c3899836a2eab2e4140838b0a0344db18677391 100644
--- a/gnome/src/actions.h
+++ b/gnome/src/actions.h
@@ -52,27 +52,27 @@
  * Initialize lists and configurations
  * @return TRUE if succeeded, FALSE otherwise
  */
-gboolean sflphone_init () ;
+gboolean sflphone_init();
 
 /**
  * Steps when closing the application.  Will ask for confirmation if a call is in progress.
  */
-void sflphone_quit () ;
+void sflphone_quit();
 
 /**
  * Hang up / refuse the current call
  */
-void sflphone_hang_up ();
+void sflphone_hang_up();
 
 /**
  * Put the selected call on hold
  */
-void sflphone_on_hold ();
+void sflphone_on_hold();
 
 /**
  * Put the selected call off hold
  */
-void sflphone_off_hold ();
+void sflphone_off_hold();
 
 /**
  * Open a new call
@@ -85,7 +85,7 @@ callable_obj_t * sflphone_new_call();
  * @param accountID The account the voice mails are for
  * @param count The number of voice mails
  */
-void sflphone_notify_voice_mail (const gchar* accountID , guint count);
+void sflphone_notify_voice_mail(const gchar* accountID, guint count);
 
 /**
  * Prepare SFLphone to transfer a call and wait for the user to dial the number to transfer to
@@ -101,49 +101,49 @@ void sflphone_unset_transfer();
 /**
  * Accept / dial the current call
  */
-void sflphone_pick_up ();
+void sflphone_pick_up();
 
 /**
  * Put the call on hold state
  * @param c The current call
  */
-void sflphone_hold (callable_obj_t * c);
+void sflphone_hold(callable_obj_t * c);
 
 /**
  * Put the call in Ringing state
  * @param c* The current call
  */
-void sflphone_ringing (callable_obj_t * c);
+void sflphone_ringing(callable_obj_t * c);
 
 /**
  * Put the call in Busy state
  * @param c* The current call
  */
-void sflphone_busy (callable_obj_t * c);
+void sflphone_busy(callable_obj_t * c);
 
 /**
  * Put the call in Failure state
  * @param c* The current call
  */
-void sflphone_fail (callable_obj_t * c);
+void sflphone_fail(callable_obj_t * c);
 
 /**
  * Put the call in Current state
  * @param c The current call
  */
-void sflphone_current (callable_obj_t * c);
+void sflphone_current(callable_obj_t * c);
 
 /**
  * The callee has hung up
  * @param c The current call
  */
-void sflphone_hung_up (callable_obj_t * c);
+void sflphone_hung_up(callable_obj_t * c);
 
 /**
  * Incoming call
  * @param c The incoming call
  */
-void sflphone_incoming_call (callable_obj_t * c);
+void sflphone_incoming_call(callable_obj_t * c);
 
 /**
  * Dial the number
@@ -151,19 +151,19 @@ void sflphone_incoming_call (callable_obj_t * c);
  * @param keyval The unique int representing the key
  * @param key The char value of the key
  */
-void sflphone_keypad (guint keyval, gchar * key);
+void sflphone_keypad(guint keyval, gchar * key);
 
 /**
  * Place a call with a filled callable_obj_t.to
  * @param c A call in CALL_STATE_DIALING state
  */
-void sflphone_place_call (callable_obj_t * c);
+void sflphone_place_call(callable_obj_t * c);
 
 /**
  * Fetch the ip2ip profile through dbus and fill
  * the internal hash table.
  */
-void sflphone_fill_ip2ip_profile (void);
+void sflphone_fill_ip2ip_profile(void);
 
 /**
  * @return The internal hash table representing
@@ -172,53 +172,52 @@ void sflphone_fill_ip2ip_profile (void);
 GHashTable *sflphone_get_ip2ip_properties(void);
 
 /**
- * Initialize the accounts data structure
+ * Get a list of accounts from the daemon and load them into account_t
+ * structures.
  */
-void sflphone_fill_account_list ();
+void sflphone_fill_account_list();
 
-void sflphone_fill_call_list (void);
+void sflphone_fill_call_list(void);
 
 /**
  * Set an account as current. The current account is to one used to place calls with by default
- * The current account is the first in the account list ( index 0 )
+ * The current account is the first in the account list( index 0 )
  */
 void sflphone_set_current_account();
 
 /**
  * Initialialize the codecs data structure
  */
-void sflphone_fill_codec_list ();
-
-void sflphone_fill_codec_list_per_account (account_t *);
+void sflphone_fill_codec_list_per_account(account_t *);
 
 void sflphone_add_participant();
 
-void sflphone_record (callable_obj_t *c);
+void sflphone_record(callable_obj_t *c);
 
-void sflphone_rec_call (void);
+void sflphone_rec_call(void);
 
-void sflphone_mute_call (void);
+void sflphone_mute_call(void);
 
-void status_bar_display_account ();
+void status_bar_display_account();
 
-void sflphone_fill_history (void);
+void sflphone_fill_history(void);
 
 /**
  * Action called when a new participant is dragged in
  */
-void sflphone_add_participant (const gchar* callID, const gchar* confID);
+void sflphone_add_participant(const gchar* callID, const gchar* confID);
 
 /**
  * Action called when a conference participant is draged out
  */
-void sflphone_detach_participant (const gchar* callID);
+void sflphone_detach_participant(const gchar* callID);
 
 /**
  * Nofity that the communication is
  * now secured using SRTP/SDES.
  * @param c* The current call
  */
-void sflphone_srtp_sdes_on (callable_obj_t * c);
+void sflphone_srtp_sdes_on(callable_obj_t * c);
 
 /**
  * Notify that the SRTP/SDES session
@@ -230,14 +229,14 @@ void sflphone_srtp_sdes_on (callable_obj_t * c);
  * now secured using ZRTP.
  * @param c* The current call
  */
-void sflphone_srtp_zrtp_on (callable_obj_t * c);
+void sflphone_srtp_zrtp_on(callable_obj_t * c);
 
 /**
  * Called when the ZRTP session goes
  * unsecured.
  * @param c* The current call
  */
-void sflphone_srtp_zrtp_off (callable_obj_t * c);
+void sflphone_srtp_zrtp_off(callable_obj_t * c);
 
 /**
  * Called when the sas has been computed
@@ -246,13 +245,14 @@ void sflphone_srtp_zrtp_off (callable_obj_t * c);
  * @param sas* The Short Authentication String
  * @param verified* Weather the SAS was confirmed or not.
  */
-void sflphone_srtp_zrtp_show_sas (callable_obj_t * c, const gchar* sas, const gboolean verified);
+void sflphone_srtp_zrtp_show_sas(callable_obj_t * c, const gchar* sas, const gboolean verified);
 
 /**
  * Called when user wants to clear.
  * @param c* The call on which to go clear
  */
-void sflphone_request_go_clear (void);
+
+void sflphone_request_go_clear(void);
 
 /**
  * Called when the UI needs to be refreshed to
@@ -262,12 +262,12 @@ void sflphone_request_go_clear (void);
  * @param description A textual description of the code
  * @param code The status code as in SIP or IAX
  */
-void sflphone_call_state_changed (callable_obj_t * c, const gchar * description, const guint code);
+void sflphone_call_state_changed(callable_obj_t * c, const gchar * description, const guint code);
 
-void sflphone_add_main_participant (const conference_obj_t * c);
+void sflphone_add_main_participant(const conference_obj_t * c);
 
-void sflphone_srtp_sdes_off (callable_obj_t * c);
+void sflphone_srtp_sdes_off(callable_obj_t * c);
 
-void sflphone_fill_conference_list (void);
+void sflphone_fill_conference_list(void);
 
 #endif
diff --git a/gnome/src/codeclist.c b/gnome/src/codeclist.c
index 9a83e5f42d1cf80b8b1a7ac801d65bce4048ffe2..6662cfe018464ca8e59d6f9f292b35958f0f6024 100644
--- a/gnome/src/codeclist.c
+++ b/gnome/src/codeclist.c
@@ -217,7 +217,7 @@ void codec_list_update_to_daemon(const account_t *acc)
     int c = 0;
     int i;
 
-    for (i = 0; i < length; i++) {
+    for (i = 0; i < length; ++i) {
         codec_t* currentCodec = codec_list_get_nth(i, acc->codecs);
 
         if (currentCodec) {
@@ -240,14 +240,14 @@ void codec_list_update_to_daemon(const account_t *acc)
 
     // Allocate NULL array at the end for Dbus
     codecList = (void*) g_realloc(codecList, (c + 1) * sizeof(void*));
-    *(codecList+c) = NULL;
+    *(codecList + c) = NULL;
 
     // call dbus function with array of strings
     dbus_set_active_audio_codec_list(codecList, acc->accountID);
 
     // Delete memory
     for (i = 0; i < c; i++)
-        g_free((gchar*) *(codecList+i));
+        g_free((gchar*) *(codecList + i) );
 
     g_free(codecList);
 }
diff --git a/gnome/src/config/accountconfigdialog.c b/gnome/src/config/accountconfigdialog.c
index 8acc9c5d8ce61fa495eb4311807b27665b8c557f..3ef15b51a39bc946bd2c34ed37619a931a508b2f 100644
--- a/gnome/src/config/accountconfigdialog.c
+++ b/gnome/src/config/accountconfigdialog.c
@@ -206,7 +206,7 @@ static GtkWidget* create_basic_tab(const account_t *account)
             password = g_hash_table_lookup(element, ACCOUNT_PASSWORD);
         }
     } else
-        password = g_hash_table_lookup(account->properties, ACCOUNT_PASSWORD);
+        password = account_lookup(account, ACCOUNT_PASSWORD);
 
     GtkWidget *frame = gnome_main_section_new(_("Account Parameters"));
     gtk_widget_show(frame);
@@ -214,7 +214,7 @@ static GtkWidget* create_basic_tab(const account_t *account)
     GtkWidget *table = NULL;
 
     if (account_is_SIP(account))
-        table = gtk_table_new(9, 2,  FALSE/* homogeneous */);
+        table = gtk_table_new(9, 2,  FALSE /* homogeneous */);
     else if (account_is_IAX(account))
         table = gtk_table_new(8, 2, FALSE);
     else {
@@ -234,7 +234,7 @@ static GtkWidget* create_basic_tab(const account_t *account)
     gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
     entry_alias = gtk_entry_new();
     gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_alias);
-    gchar *alias = g_hash_table_lookup(account->properties, ACCOUNT_ALIAS);
+    gchar *alias = account_lookup(account, ACCOUNT_ALIAS);
     gtk_entry_set_text(GTK_ENTRY(entry_alias), alias);
     gtk_table_attach(GTK_TABLE(table), entry_alias, 1, 2, row, row + 1,
                      GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
@@ -276,8 +276,7 @@ static GtkWidget* create_basic_tab(const account_t *account)
     gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
     entry_hostname = gtk_entry_new();
     gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_hostname);
-    const gchar *hostname = g_hash_table_lookup(account->properties,
-                                                    ACCOUNT_HOSTNAME);
+    const gchar *hostname = account_lookup(account, ACCOUNT_HOSTNAME);
     gtk_entry_set_text(GTK_ENTRY(entry_hostname), hostname);
     gtk_table_attach(GTK_TABLE(table), entry_hostname, 1, 2, row, row + 1,
                      GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
@@ -293,7 +292,7 @@ static GtkWidget* create_basic_tab(const account_t *account)
                                    GTK_ENTRY_ICON_PRIMARY,
                                    gdk_pixbuf_new_from_file(PERSON_IMG, NULL));
     gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_username);
-    gchar *username = g_hash_table_lookup(account->properties, ACCOUNT_USERNAME);
+    gchar *username = account_lookup(account, ACCOUNT_USERNAME);
     gtk_entry_set_text(GTK_ENTRY(entry_username), username);
     gtk_table_attach(GTK_TABLE(table), entry_username, 1, 2, row, row + 1,
                      GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
@@ -337,7 +336,7 @@ static GtkWidget* create_basic_tab(const account_t *account)
     gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
     entry_route_set = gtk_entry_new();
     gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_route_set);
-    gchar *route_set = g_hash_table_lookup(account->properties, ACCOUNT_ROUTE);
+    gchar *route_set = account_lookup(account, ACCOUNT_ROUTE);
     gtk_entry_set_text(GTK_ENTRY(entry_route_set), route_set);
     gtk_table_attach(GTK_TABLE(table), entry_route_set, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
 
@@ -347,7 +346,7 @@ static GtkWidget* create_basic_tab(const account_t *account)
     gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
     entry_mailbox = gtk_entry_new();
     gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_mailbox);
-    gchar *mailbox = g_hash_table_lookup(account->properties, ACCOUNT_MAILBOX);
+    gchar *mailbox = account_lookup(account, ACCOUNT_MAILBOX);
     mailbox = mailbox ? mailbox : "";
     gtk_entry_set_text(GTK_ENTRY(entry_mailbox), mailbox);
     gtk_table_attach(GTK_TABLE(table), entry_mailbox, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
@@ -358,7 +357,7 @@ static GtkWidget* create_basic_tab(const account_t *account)
     gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
     entry_user_agent = gtk_entry_new();
     gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_user_agent);
-    gchar *user_agent = g_hash_table_lookup(account->properties, ACCOUNT_USERAGENT);
+    gchar *user_agent = account_lookup(account, ACCOUNT_USERAGENT);
     gtk_entry_set_text(GTK_ENTRY(entry_user_agent), user_agent);
     gtk_table_attach(GTK_TABLE(table), entry_user_agent, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
 
@@ -418,7 +417,6 @@ delete_credential_cb(GtkWidget *button UNUSED, gpointer data)
         GtkTreePath *path;
         path = gtk_tree_model_get_path(model, &iter);
         gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
-
         gtk_tree_path_free(path);
     }
 }
@@ -662,7 +660,7 @@ static GtkWidget* create_credential_widget(const account_t *account)
                                          G_TYPE_STRING,  // Username
                                          G_TYPE_STRING,  // Password
                                          G_TYPE_POINTER  // Pointer to the Objectc
-                                        );
+                                         );
 
     treeview_credential = gtk_tree_view_new_with_model(GTK_TREE_MODEL(credential_store));
     GtkTreeSelection * tree_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview_credential));
@@ -726,17 +724,16 @@ create_security_widget(const account_t *account)
 
     // Load from SIP/IAX/Unknown ?
     if (account && account->properties) {
-        curKeyExchange = g_hash_table_lookup(account->properties,
-                                             ACCOUNT_KEY_EXCHANGE);
+        curKeyExchange = account_lookup(account, ACCOUNT_KEY_EXCHANGE);
         if (curKeyExchange == NULL)
             curKeyExchange = "none";
 
-        curSRTPEnabled = g_hash_table_lookup(account->properties, ACCOUNT_SRTP_ENABLED);
+        curSRTPEnabled = account_lookup(account, ACCOUNT_SRTP_ENABLED);
 
         if (curSRTPEnabled == NULL)
             curSRTPEnabled = "false";
 
-        curTLSEnabled = g_hash_table_lookup(account->properties, TLS_ENABLE);
+        curTLSEnabled = account_lookup(account, TLS_ENABLE);
 
         if (curTLSEnabled == NULL)
             curTLSEnabled = "false";
@@ -830,7 +827,7 @@ static GtkWidget* create_registration_expire(const account_t *account)
                                           &orig_key, (gpointer) &account_expire))
             ERROR("Could not retrieve %s from account properties",
                   ACCOUNT_REGISTRATION_EXPIRE);
-    
+
     GtkWidget *table, *frame;
     gnome_main_section_new_with_table(_("Registration"), &frame, &table, 2, 3);
     gtk_container_set_border_width(GTK_CONTAINER(table), 10);
@@ -854,8 +851,8 @@ create_network(const account_t *account)
     gchar *local_port = NULL;
 
     if (account) {
-        local_interface = g_hash_table_lookup(account->properties, LOCAL_INTERFACE);
-        local_port = g_hash_table_lookup(account->properties, LOCAL_PORT);
+        local_interface = account_lookup(account, LOCAL_INTERFACE);
+        local_port = account_lookup(account, LOCAL_PORT);
     }
 
     GtkWidget *table, *frame;
@@ -922,20 +919,20 @@ GtkWidget* create_published_address(const account_t *account)
 
     // Get the user configuration
     if (account) {
-        use_tls = g_hash_table_lookup(account->properties, TLS_ENABLE);
-        published_sameas_local = g_hash_table_lookup(account->properties, PUBLISHED_SAMEAS_LOCAL);
+        use_tls = account_lookup(account, TLS_ENABLE);
+        published_sameas_local = account_lookup(account, PUBLISHED_SAMEAS_LOCAL);
 
         if (utf8_case_equal(published_sameas_local, "true")) {
-            published_address = dbus_get_address_from_interface_name(g_hash_table_lookup(account->properties, LOCAL_INTERFACE));
-            published_port = g_hash_table_lookup(account->properties, LOCAL_PORT);
+            published_address = dbus_get_address_from_interface_name(account_lookup(account, LOCAL_INTERFACE));
+            published_port = account_lookup(account, LOCAL_PORT);
         } else {
-            published_address = g_hash_table_lookup(account->properties, PUBLISHED_ADDRESS);
-            published_port = g_hash_table_lookup(account->properties, PUBLISHED_PORT);
+            published_address = account_lookup(account, PUBLISHED_ADDRESS);
+            published_port = account_lookup(account, PUBLISHED_PORT);
         }
 
-        stun_enable = g_hash_table_lookup(account->properties, ACCOUNT_SIP_STUN_ENABLED);
-        stun_server = g_hash_table_lookup(account->properties, ACCOUNT_SIP_STUN_SERVER);
-        published_sameas_local = g_hash_table_lookup(account->properties, PUBLISHED_SAMEAS_LOCAL);
+        stun_enable = account_lookup(account, ACCOUNT_SIP_STUN_ENABLED);
+        stun_server = account_lookup(account, ACCOUNT_SIP_STUN_SERVER);
+        published_sameas_local = account_lookup(account, PUBLISHED_SAMEAS_LOCAL);
     }
 
     gnome_main_section_new_with_table(_("Published address"), &frame, &table, 2, 3);
@@ -1061,7 +1058,7 @@ create_audiocodecs_configuration(const account_t *account)
         gtk_widget_show(dtmf);
 
         overrtp = gtk_radio_button_new_with_label(NULL, _("RTP"));
-        const gchar * const dtmf_type = g_hash_table_lookup(account->properties, ACCOUNT_DTMF_TYPE);
+        const gchar * const dtmf_type = account_lookup(account, ACCOUNT_DTMF_TYPE);
         const gboolean dtmf_are_rtp = utf8_case_equal(dtmf_type, OVERRTP);
         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(overrtp), dtmf_are_rtp);
         gtk_table_attach(GTK_TABLE(table), overrtp, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
@@ -1079,7 +1076,7 @@ create_audiocodecs_configuration(const account_t *account)
 
     file_chooser = gtk_file_chooser_button_new(_("Choose a ringtone"), GTK_FILE_CHOOSER_ACTION_OPEN);
 
-    gpointer ptr = g_hash_table_lookup(account->properties, CONFIG_RINGTONE_ENABLED);
+    gpointer ptr = account_lookup(account, CONFIG_RINGTONE_ENABLED);
     enable_tone = gtk_check_button_new_with_mnemonic(_("_Enable ringtones"));
     const gboolean ringtone_enabled = g_strcmp0(ptr, "true") == 0;
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enable_tone), ringtone_enabled);
@@ -1088,7 +1085,7 @@ create_audiocodecs_configuration(const account_t *account)
 
     // file chooser button
     gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_chooser) , g_get_home_dir());
-    ptr = g_hash_table_lookup(account->properties, CONFIG_RINGTONE_PATH);
+    ptr = account_lookup(account, CONFIG_RINGTONE_PATH);
     gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(file_chooser) , ptr);
     gtk_widget_set_sensitive(file_chooser, ringtone_enabled);
 
@@ -1236,7 +1233,44 @@ static void update_account_from_basic_tab(account_t *account)
     g_free(proto);
 }
 
-void show_account_window(account_t *account)
+void update_account_from_dialog(GtkWidget *dialog, account_t *account)
+{
+    if (!dialog)
+        return;
+
+    const gboolean IS_IP2IP = account_is_IP2IP(account);
+    if (!IS_IP2IP)
+        update_account_from_basic_tab(account);
+
+    // Get current protocol for this account
+    gchar *current_protocol;
+    if (protocol_combo)
+        current_protocol = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(protocol_combo));
+    else
+        current_protocol = g_strdup("SIP");
+
+    if (!IS_IP2IP && g_strcmp0(current_protocol, "SIP") == 0)
+        account->credential_information = get_new_credential();
+
+    /** @todo Verify if it's the best condition to check */
+    if (g_strcmp0(account->accountID, "new") == 0) {
+        dbus_add_account(account);
+        if (account->credential_information)
+            dbus_set_credentials(account);
+    } else {
+        if (account->credential_information)
+            dbus_set_credentials(account);
+        dbus_set_account_details(account);
+    }
+
+    // propagate changes to the daemon
+    codec_list_update_to_daemon(account);
+
+    g_free(current_protocol);
+    gtk_widget_destroy(dialog);
+}
+
+GtkWidget *show_account_window(const account_t *account)
 {
     // First we reset
     reset();
@@ -1256,9 +1290,10 @@ void show_account_window(account_t *account)
     gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), notebook, TRUE, TRUE, 0);
     gtk_container_set_border_width(GTK_CONTAINER(notebook), 10);
     gtk_widget_show(notebook);
+    const gboolean IS_IP2IP = account_is_IP2IP(account);
 
     // We do not need the global settings for the IP2IP account
-    if (!account_is_IP2IP(account)) {
+    if (!IS_IP2IP) {
         /* General Settings */
         GtkWidget *basic_tab = create_basic_tab(account);
         gtk_notebook_append_page(GTK_NOTEBOOK(notebook), basic_tab, gtk_label_new(_("Basic")));
@@ -1270,22 +1305,14 @@ void show_account_window(account_t *account)
     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), audiocodecs_tab, gtk_label_new(_("Audio")));
     gtk_notebook_page_num(GTK_NOTEBOOK(notebook), audiocodecs_tab);
 
-    // Get current protocol for this account
-    gchar *current_protocol;
-    if (protocol_combo)
-        current_protocol = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(protocol_combo));
-    else
-        current_protocol = g_strdup("SIP");
-
     // Do not need advanced or security one for the IP2IP account
-    if (!account_is_IP2IP(account)) {
+    if (!IS_IP2IP) {
         /* Advanced */
         advanced_tab = create_advanced_tab(account);
         gtk_notebook_append_page(GTK_NOTEBOOK(notebook), advanced_tab, gtk_label_new(_("Advanced")));
         gtk_notebook_page_num(GTK_NOTEBOOK(notebook), advanced_tab);
 
         /* Security */
-        initialize_credential_information(account);
         security_tab = create_security_tab(account);
         gtk_notebook_append_page(GTK_NOTEBOOK(notebook), security_tab, gtk_label_new(_("Security")));
         gtk_notebook_page_num(GTK_NOTEBOOK(notebook), security_tab);
@@ -1302,41 +1329,15 @@ void show_account_window(account_t *account)
 
     gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0);
 
-    /* Run dialog */
+    /* Run dialog, this blocks */
     gint response = gtk_dialog_run(GTK_DIALOG(dialog));
 
-    // If cancel button is pressed
-    if (response == GTK_RESPONSE_CANCEL) {
+    // If anything but "Apply" button is pressed
+    if (response != GTK_RESPONSE_ACCEPT) {
         gtk_widget_destroy(dialog);
-        return;
-    }
-
-    if (!account_is_IP2IP(account))
-        update_account_from_basic_tab(account);
-
-    /** @todo Verify if it's the best condition to check */
-    if (utf8_case_equal(account->accountID, "new"))
-        dbus_add_account(account);
-    else
-        dbus_set_account_details(account);
-
-    if (g_strcmp0(current_protocol, "SIP") == 0) {
-        /* Set new credentials if any */
-        DEBUG("Config: Setting credentials");
-
-        if (!account_is_IP2IP(account)) {
-            DEBUG("Config: Get new credentials");
-            account->credential_information = get_new_credential();
-
-            if (account->credential_information)
-                dbus_set_credentials(account);
-        }
+        return NULL;
+    } else {
+        return dialog;
     }
-
-    // propagate changes to the daemon
-    codec_list_update_to_daemon(account);
-
-    gtk_widget_destroy(dialog);
-    g_free(current_protocol);
 }
 
diff --git a/gnome/src/config/accountconfigdialog.h b/gnome/src/config/accountconfigdialog.h
index 1683b269c294942f13acd85399639f4be68cf253..43cfe666e6c6fd57ece795a41bbc113280138b27 100644
--- a/gnome/src/config/accountconfigdialog.h
+++ b/gnome/src/config/accountconfigdialog.h
@@ -40,7 +40,18 @@
 /**
  * Display the main account widget
  * @param a The account you want to display
+ * @return The dialog with the pertinent account information
  */
-void show_account_window(account_t *a);
+GtkWidget *show_account_window(const account_t *a);
+
+/*
+ * @param dialog The dialog the account will be update from
+ * @param a The account you want to display
+ */
+void update_account_from_dialog(GtkWidget *dialog, account_t *a);
+
+/**
+ * Resets local cache of account pointers */
+void reset_account_store();
 
 #endif
diff --git a/gnome/src/config/accountlistconfigdialog.c b/gnome/src/config/accountlistconfigdialog.c
index 31de47d48c02e6528c5bda9dd6ba43d523fa60cf..27560b0200c74d898e506bc36f84768f53563fb5 100644
--- a/gnome/src/config/accountlistconfigdialog.c
+++ b/gnome/src/config/accountlistconfigdialog.c
@@ -44,15 +44,13 @@
 
 static const int CONTEXT_ID_REGISTRATION = 0;
 
-static GtkWidget *add_button;
 static GtkWidget *edit_button;
 static GtkWidget *delete_button;
 static GtkWidget *move_down_button;
 static GtkWidget *move_up_button;
-static GtkWidget *status_bar;
+static GtkWidget *account_list_status_bar;
 static GtkListStore *account_store;
 static GtkDialog *account_list_dialog;
-static account_t *selected_account;
 
 // Account properties
 enum {
@@ -60,72 +58,125 @@ enum {
     COLUMN_ACCOUNT_TYPE,
     COLUMN_ACCOUNT_STATUS,
     COLUMN_ACCOUNT_ACTIVE,
-    COLUMN_ACCOUNT_DATA,
+    COLUMN_ACCOUNT_ID,
     COLUMN_ACCOUNT_COUNT
 };
 
-static void delete_account_cb(void)
+/* Get selected account ID from treeview
+ * @return copied selected_accountID, must be freed by caller */
+static gchar *
+get_selected_accountID(GtkTreeView *tree_view)
 {
-    RETURN_IF_NULL(selected_account, "No selected account in delete action");
-    dbus_remove_account(selected_account->accountID);
-    selected_account = NULL;
+    GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
+    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
+
+    // Find selected iteration and create a copy
+    GtkTreeIter iter;
+    gtk_tree_selection_get_selected(selection, &model, &iter);
+    // The Gvalue will be initialized in the following function
+    GValue val;
+    memset(&val, 0, sizeof(val));
+    gtk_tree_model_get_value(model, &iter, COLUMN_ACCOUNT_ID, &val);
+
+    gchar *selected_accountID = g_strdup(g_value_get_string(&val));
+    g_value_unset(&val);
+    return selected_accountID;
 }
 
-static void row_activated_cb(GtkTreeView *view UNUSED,
-                             GtkTreePath *path UNUSED,
-                             GtkTreeViewColumn *col UNUSED,
-                             gpointer user_data UNUSED)
+static gboolean
+find_account_in_account_store(const gchar *accountID, GtkTreeModel *model,
+                              GtkTreeIter *iter)
+{
+    gboolean valid = gtk_tree_model_get_iter_first(model, iter);
+    gboolean found = FALSE;
+    while (valid && !found) {
+        gchar *id;
+        gtk_tree_model_get(model, iter, COLUMN_ACCOUNT_ID, &id, -1);
+        if (g_strcmp0(id, accountID) == 0)
+            found = TRUE;
+        else
+            valid = gtk_tree_model_iter_next(model, iter);
+        g_free(id);
+    }
+    return found;
+}
+
+
+static void delete_account_cb(GtkButton *button UNUSED, gpointer data)
 {
-    RETURN_IF_NULL(selected_account, "No selected account in edit action");
-    DEBUG("%s: accountID=%s\n", __PRETTY_FUNCTION__, selected_account->accountID);
-    show_account_window(selected_account);
+    gchar *selected_accountID = get_selected_accountID(data);
+    RETURN_IF_NULL(selected_accountID, "No selected account in delete action");
+    GtkTreeModel *model = GTK_TREE_MODEL(account_store);
+    GtkTreeIter iter;
+    if (find_account_in_account_store(selected_accountID, model, &iter))
+        gtk_list_store_remove(account_store, &iter);
+
+    dbus_remove_account(selected_accountID);
+    g_free(selected_accountID);
 }
 
-static void edit_account_cb(GtkButton *button UNUSED, gpointer data UNUSED)
+static void
+run_account_dialog(const gchar *selected_accountID)
 {
-    RETURN_IF_NULL(selected_account, "No selected account in edit action");
-    DEBUG("%s: accountID=%s\n", __PRETTY_FUNCTION__, selected_account->accountID);
-    show_account_window(selected_account);
+    account_t *account = account_list_get_by_id(selected_accountID);
+    GtkWidget *dialog = show_account_window(account);
+    update_account_from_dialog(dialog, account);
 }
 
-static void add_account_cb(void)
+static void row_activated_cb(GtkTreeView *view,
+                             GtkTreePath *path UNUSED,
+                             GtkTreeViewColumn *col UNUSED,
+                             gpointer user_data UNUSED)
 {
-    account_t *new_account = create_default_account();
-    show_account_window(new_account);
+    gchar *selected_accountID = get_selected_accountID(view);
+    RETURN_IF_NULL(selected_accountID, "No selected account ID");
+    run_account_dialog(selected_accountID);
+    g_free(selected_accountID);
 }
 
-static void account_store_fill(GtkTreeIter *iter, account_t *a)
+static void edit_account_cb(GtkButton *button UNUSED, gpointer data)
 {
-    const gchar *enabled = g_hash_table_lookup(a->properties, ACCOUNT_ENABLED);
-    const gchar *type = g_hash_table_lookup(a->properties, ACCOUNT_TYPE);
-    DEBUG("Config: Filling accounts: Account is enabled :%s", enabled);
+    gchar *selected_accountID = get_selected_accountID(data);
+    RETURN_IF_NULL(selected_accountID, "No selected account ID");
+    run_account_dialog(selected_accountID);
+    g_free(selected_accountID);
+}
+
+static void account_store_add(GtkTreeIter *iter, account_t *account)
+{
+    const gchar *enabled = account_lookup(account, ACCOUNT_ENABLED);
+    const gchar *type = account_lookup(account, ACCOUNT_TYPE);
+    DEBUG("Config: Adding account: Account is enabled :%s", enabled);
+    const gchar *state_name = account_state_name(account->state);
 
-    gtk_list_store_set(account_store, iter, COLUMN_ACCOUNT_ALIAS,
-                       g_hash_table_lookup(a->properties, ACCOUNT_ALIAS),
+    gtk_list_store_set(account_store, iter,
+                       COLUMN_ACCOUNT_ALIAS, account_lookup(account, ACCOUNT_ALIAS),
                        COLUMN_ACCOUNT_TYPE, type,
-                       COLUMN_ACCOUNT_STATUS, account_state_name(a->state),
+                       COLUMN_ACCOUNT_STATUS, state_name,
                        COLUMN_ACCOUNT_ACTIVE, utf8_case_equal(enabled, "true"),
-                       COLUMN_ACCOUNT_DATA, a, -1);
+                       COLUMN_ACCOUNT_ID, account->accountID, -1);
 }
 
+
+
 /**
- * Fills the treelist with accounts
+ * Fills the treelist with accounts, should be called whenever the account
+ * list is modified.
  */
-void account_list_config_dialog_fill()
+static void account_store_fill()
 {
     RETURN_IF_NULL(account_list_dialog, "No account dialog");
-
     gtk_list_store_clear(account_store);
 
     // IP2IP account must be first
-    account_t *ip2ip = account_list_get_by_id("IP2IP");
-
+    account_t *ip2ip = account_list_get_by_id(IP2IP_PROFILE);
+    ip2ip->state = ACCOUNT_STATE_IP2IP_READY;
     RETURN_IF_NULL(ip2ip, "Could not find IP2IP account");
 
     GtkTreeIter iter;
     gtk_list_store_append(account_store, &iter);
 
-    account_store_fill(&iter, ip2ip);
+    account_store_add(&iter, ip2ip);
 
     for (size_t i = 0; i < account_list_get_size(); ++i) {
         account_t *a = account_list_get_nth(i);
@@ -134,11 +185,19 @@ void account_list_config_dialog_fill()
         // we don't want to process the IP2IP twice
         if (a != ip2ip) {
             gtk_list_store_append(account_store, &iter);
-            account_store_fill(&iter, a);
+            account_store_add(&iter, a);
         }
     }
 }
 
+static void add_account_cb(void)
+{
+    account_t *new_account = create_default_account();
+    account_list_add(new_account);
+    run_account_dialog(new_account->accountID);
+    account_store_fill();
+}
+
 /**
  * Call back when the user click on an account in the list
  */
@@ -147,7 +206,6 @@ select_account_cb(GtkTreeSelection *selection, GtkTreeModel *model)
 {
     GtkTreeIter iter;
     if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
-        selected_account = NULL;
         gtk_widget_set_sensitive(move_up_button, FALSE);
         gtk_widget_set_sensitive(move_down_button, FALSE);
         gtk_widget_set_sensitive(edit_button, FALSE);
@@ -158,13 +216,14 @@ select_account_cb(GtkTreeSelection *selection, GtkTreeModel *model)
     // The Gvalue will be initialized in the following function
     GValue val;
     memset(&val, 0, sizeof(val));
-    gtk_tree_model_get_value(model, &iter, COLUMN_ACCOUNT_DATA, &val);
+    gtk_tree_model_get_value(model, &iter, COLUMN_ACCOUNT_ID, &val);
 
-    selected_account = (account_t*) g_value_get_pointer(&val);
+    gchar *selected_accountID = g_value_dup_string(&val);
     g_value_unset(&val);
 
+    DEBUG("Selected account has accountID %s", selected_accountID);
+    account_t *selected_account = account_list_get_by_id(selected_accountID);
     RETURN_IF_NULL(selected_account, "Selected account is NULL");
-    DEBUG("Selected account has accountID %s", selected_account->accountID);
 
     gtk_widget_set_sensitive(edit_button, TRUE);
 
@@ -174,33 +233,13 @@ select_account_cb(GtkTreeSelection *selection, GtkTreeModel *model)
         gtk_widget_set_sensitive(delete_button, TRUE);
 
         /* Update status bar about current registration state */
-        gtk_statusbar_pop(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION);
-
-        const gchar *state_name = account_state_name(selected_account->state);
-        if (selected_account->protocol_state_description != NULL
-                && selected_account->protocol_state_code != 0) {
-
-            gchar * response = g_strdup_printf(
-                                   _("Server returned \"%s\" (%d)"),
-                                   selected_account->protocol_state_description,
-                                   selected_account->protocol_state_code);
-            gchar * message = g_strconcat(state_name, ". ", response, NULL);
-            gtk_statusbar_push(GTK_STATUSBAR(status_bar),
-                               CONTEXT_ID_REGISTRATION, message);
-
-            g_free(response);
-            g_free(message);
-
-        } else {
-            gtk_statusbar_push(GTK_STATUSBAR(status_bar),
-                               CONTEXT_ID_REGISTRATION, state_name);
-        }
+        update_account_list_status_bar(selected_account);
     } else {
         gtk_widget_set_sensitive(move_up_button, FALSE);
         gtk_widget_set_sensitive(move_down_button, FALSE);
         gtk_widget_set_sensitive(delete_button, FALSE);
     }
-    DEBUG("Selecting account in account window");
+    g_free(selected_accountID);
 }
 
 static void
@@ -208,7 +247,7 @@ enable_account_cb(GtkCellRendererToggle *rend UNUSED, gchar* path,
                   gpointer data)
 {
     // The IP2IP profile can't be disabled
-    if (utf8_case_equal(path, "0"))
+    if (g_strcmp0(path, "0") == 0)
         return;
 
     // Get pointer on object
@@ -217,24 +256,24 @@ enable_account_cb(GtkCellRendererToggle *rend UNUSED, gchar* path,
     GtkTreeIter iter;
     gtk_tree_model_get_iter(model, &iter, tree_path);
     gboolean enable;
-    account_t* acc;
+    gchar *id;
     gtk_tree_model_get(model, &iter, COLUMN_ACCOUNT_ACTIVE, &enable,
-                       COLUMN_ACCOUNT_DATA, &acc, -1);
+                       COLUMN_ACCOUNT_ID, &id, -1);
+
+    account_t *account = account_list_get_by_id(id);
+    g_assert(account);
     enable = !enable;
 
-    DEBUG("Account is %d enabled", enable);
     // Store value
     gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_ACCOUNT_ACTIVE,
                        enable, -1);
 
     // Modify account state
-    gchar * registration_state = enable ? g_strdup("true") : g_strdup("false");
-
-    DEBUG("Replacing registration state with %s", registration_state);
-    g_hash_table_replace(acc->properties, g_strdup(ACCOUNT_ENABLED),
-                         registration_state);
+    const gchar * enabled_str = enable ? "true" : "false";
+    DEBUG("Account is enabled: %s", enabled_str);
 
-    dbus_send_register(acc->accountID, enable);
+    account_replace(account, ACCOUNT_ENABLED, enabled_str);
+    dbus_send_register(account->accountID, enable);
 }
 
 /**
@@ -243,7 +282,7 @@ enable_account_cb(GtkCellRendererToggle *rend UNUSED, gchar* path,
 static void
 account_move(gboolean move_up, gpointer data)
 {
-    // Get view, model and selection of codec store
+    // Get view, model and selection of account
     GtkTreeView *tree_view = GTK_TREE_VIEW(data);
     GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
     GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
@@ -259,7 +298,7 @@ account_move(gboolean move_up, gpointer data)
 
     // The first real account in the list can't move up because of the IP2IP account
     // It can still move down though
-    if (utf8_case_equal(path, "1") && move_up)
+    if (g_strcmp0(path, "1") == 0 && move_up)
         return;
 
     GtkTreePath *tree_path = gtk_tree_path_new_from_string(path);
@@ -343,13 +382,12 @@ highlight_ip_profile(GtkTreeViewColumn *col UNUSED, GtkCellRenderer *rend,
 {
     GValue val;
     memset(&val, 0, sizeof(val));
-    gtk_tree_model_get_value(tree_model, iter, COLUMN_ACCOUNT_DATA, &val);
-    account_t *current = (account_t*) g_value_get_pointer(&val);
-
+    gtk_tree_model_get_value(tree_model, iter, COLUMN_ACCOUNT_ID, &val);
+    account_t *current = account_list_get_by_id(g_value_get_string(&val));
     g_value_unset(&val);
 
-    if (current != NULL) {
-        // Make the first line appear differently
+    // Make the IP2IP account  appear differently
+    if (current) {
         if (account_is_IP2IP(current)) {
             g_object_set(G_OBJECT(rend), "weight", PANGO_WEIGHT_THIN, "style",
                          PANGO_STYLE_ITALIC, "stretch",
@@ -381,8 +419,8 @@ highlight_registration(GtkTreeViewColumn *col UNUSED, GtkCellRenderer *rend,
 {
     GValue val;
     memset(&val, 0, sizeof(val));
-    gtk_tree_model_get_value(tree_model, iter, COLUMN_ACCOUNT_DATA, &val);
-    account_t *current = (account_t*) g_value_get_pointer(&val);
+    gtk_tree_model_get_value(tree_model, iter, COLUMN_ACCOUNT_ID, &val);
+    account_t *current = account_list_get_by_id(g_value_get_string(&val));
     g_value_unset(&val);
 
     if (current)
@@ -395,7 +433,6 @@ highlight_registration(GtkTreeViewColumn *col UNUSED, GtkCellRenderer *rend,
 static GtkWidget*
 create_account_list()
 {
-    selected_account = NULL;
     GtkWidget *table = gtk_table_new(1, 2, FALSE /* homogeneous */);
     gtk_table_set_col_spacings(GTK_TABLE(table), 10);
     gtk_container_set_border_width(GTK_CONTAINER(table), 10);
@@ -413,23 +450,22 @@ create_account_list()
                                        G_TYPE_STRING,  // Protocol
                                        G_TYPE_STRING,  // Status
                                        G_TYPE_BOOLEAN, // Enabled / Disabled
-                                       G_TYPE_POINTER  // Pointer to the Object
+                                       G_TYPE_STRING   // AccountID
                                       );
 
-    account_list_config_dialog_fill();
+    account_store_fill();
 
     GtkTreeView * tree_view = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(account_store)));
     GtkTreeSelection *tree_selection = gtk_tree_view_get_selection(tree_view);
     g_signal_connect(G_OBJECT(tree_selection), "changed",
-                     G_CALLBACK(select_account_cb),
-                     account_store);
+                     G_CALLBACK(select_account_cb), NULL);
 
     GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new();
     GtkTreeViewColumn *tree_view_column =
         gtk_tree_view_column_new_with_attributes("Enabled", renderer, "active",
                                                  COLUMN_ACCOUNT_ACTIVE , NULL);
     gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), tree_view_column);
-    g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(enable_account_cb), (gpointer) tree_view);
+    g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(enable_account_cb), tree_view);
 
     renderer = gtk_cell_renderer_text_new();
     tree_view_column = gtk_tree_view_column_new_with_attributes("Alias",
@@ -457,8 +493,7 @@ create_account_list()
     renderer = gtk_cell_renderer_text_new();
     tree_view_column = gtk_tree_view_column_new_with_attributes(_("Status"),
                      renderer,
-                     "markup", COLUMN_ACCOUNT_STATUS,
-                     NULL);
+                     "markup", COLUMN_ACCOUNT_STATUS, NULL);
     gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), tree_view_column);
     // Highlight IP profile
     gtk_tree_view_column_set_cell_data_func(tree_view_column, renderer,
@@ -491,20 +526,20 @@ create_account_list()
     g_signal_connect(G_OBJECT(move_down_button), "clicked",
                      G_CALLBACK(move_down_cb), tree_view);
 
-    add_button = gtk_button_new_from_stock(GTK_STOCK_ADD);
+    GtkWidget *add_button = gtk_button_new_from_stock(GTK_STOCK_ADD);
     g_signal_connect_swapped(G_OBJECT(add_button), "clicked",
                              G_CALLBACK(add_account_cb), NULL);
     gtk_box_pack_start(GTK_BOX(button_box), add_button, FALSE, FALSE, 0);
 
     edit_button = gtk_button_new_from_stock(GTK_STOCK_EDIT);
     gtk_widget_set_sensitive(edit_button, FALSE);
-    g_signal_connect(G_OBJECT(edit_button), "clicked", G_CALLBACK(edit_account_cb), NULL);
+    g_signal_connect(G_OBJECT(edit_button), "clicked", G_CALLBACK(edit_account_cb), tree_view);
     gtk_box_pack_start(GTK_BOX(button_box), edit_button, FALSE, FALSE, 0);
 
     delete_button = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
     gtk_widget_set_sensitive(delete_button, FALSE);
-    g_signal_connect_swapped(G_OBJECT(delete_button), "clicked",
-                             G_CALLBACK(delete_account_cb), NULL);
+    g_signal_connect(G_OBJECT(delete_button), "clicked",
+                     G_CALLBACK(delete_account_cb), tree_view);
     gtk_box_pack_start(GTK_BOX(button_box), delete_button, FALSE, FALSE, 0);
 
     /* help and close buttons */
@@ -539,6 +574,39 @@ create_account_list()
     return table;
 }
 
+void update_account_list_status_bar(account_t *account)
+{
+    if (!account || !account_list_status_bar)
+        return;
+
+    /* Update status bar about current registration state */
+    gtk_statusbar_pop(GTK_STATUSBAR(account_list_status_bar),
+                      CONTEXT_ID_REGISTRATION);
+
+    const gchar *state_name = account_state_name(account->state);
+    if (account->protocol_state_description != NULL &&
+        account->protocol_state_code != 0) {
+
+        gchar * response = g_strdup_printf(_("Server returned \"%s\" (%d)"),
+                                           account->protocol_state_description,
+                                           account->protocol_state_code);
+        gchar * message = g_strconcat(state_name, ". ", response, NULL);
+        gtk_statusbar_push(GTK_STATUSBAR(account_list_status_bar),
+                           CONTEXT_ID_REGISTRATION, message);
+
+        g_free(response);
+        g_free(message);
+    } else {
+        gtk_statusbar_push(GTK_STATUSBAR(account_list_status_bar),
+                           CONTEXT_ID_REGISTRATION, state_name);
+    }
+
+    GtkTreeModel *model = GTK_TREE_MODEL(account_store);
+    GtkTreeIter iter;
+    if (find_account_in_account_store(account->accountID, model, &iter))
+        gtk_list_store_set(account_store, &iter, COLUMN_ACCOUNT_STATUS, state_name, -1);
+}
+
 void show_account_list_config_dialog(void)
 {
     account_list_dialog = GTK_DIALOG(gtk_dialog_new_with_buttons(_("Accounts"),
@@ -561,9 +629,9 @@ void show_account_list_config_dialog(void)
     gtk_container_add(GTK_CONTAINER(accountFrame), tab);
 
     /* Status bar for the account list */
-    status_bar = gtk_statusbar_new();
-    gtk_widget_show(status_bar);
-    gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(account_list_dialog)), status_bar, TRUE, TRUE, 0);
+    account_list_status_bar = gtk_statusbar_new();
+    gtk_widget_show(account_list_status_bar);
+    gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(account_list_dialog)), account_list_status_bar, TRUE, TRUE, 0);
 
     const gint num_accounts = account_list_get_registered_accounts();
 
@@ -571,11 +639,11 @@ void show_account_list_config_dialog(void)
         gchar * message = g_strdup_printf(n_("There is %d active account",
                                              "There are %d active accounts",
                                              num_accounts), num_accounts);
-        gtk_statusbar_push(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION,
+        gtk_statusbar_push(GTK_STATUSBAR(account_list_status_bar), CONTEXT_ID_REGISTRATION,
                            message);
         g_free(message);
     } else {
-        gtk_statusbar_push(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION,
+        gtk_statusbar_push(GTK_STATUSBAR(account_list_status_bar), CONTEXT_ID_REGISTRATION,
                            _("You have no active account"));
     }
 
@@ -584,7 +652,16 @@ void show_account_list_config_dialog(void)
     status_bar_display_account();
 
     gtk_widget_destroy(GTK_WIDGET(account_list_dialog));
+
+    /* Invalidate static pointers */
     account_list_dialog = NULL;
+    account_list_status_bar = NULL;
+    edit_button = NULL;
+    delete_button = NULL;
+    move_down_button = NULL;
+    move_up_button = NULL;
+    account_store = NULL;
+
     update_actions();
 }
 
diff --git a/gnome/src/config/accountlistconfigdialog.h b/gnome/src/config/accountlistconfigdialog.h
index 40e58526dbaab07a3ad233e8ddebdb7640eb1fb5..bae376b6d92152cd13c6dc43fcb0dc3765a34cca 100644
--- a/gnome/src/config/accountlistconfigdialog.h
+++ b/gnome/src/config/accountlistconfigdialog.h
@@ -29,12 +29,12 @@
  */
 
 
-#ifndef __SFL_ACCOUNTLISTDIALOG_H__
-#define __SFL_ACCOUNTLISTDIALOG_H__
+#ifndef ACCOUNTLISTDIALOG_H_
+#define ACCOUNTLISTDIALOG_H_
 
-#include <sflphone_const.h>
+#include "accountlist.h"
 
 void show_account_list_config_dialog(void);
-void account_list_config_dialog_fill(void);
+void update_account_list_status_bar(account_t *account);
 
-#endif
+#endif // ACCOUNTLISTDIALOG_H_
diff --git a/gnome/src/dbus/configurationmanager-introspec.xml b/gnome/src/dbus/configurationmanager-introspec.xml
index f22a7ead0c531f917e37e800d4c46fc56f2314da..a990a0be463994ea5c61a68778e615f23be1c61c 100644
--- a/gnome/src/dbus/configurationmanager-introspec.xml
+++ b/gnome/src/dbus/configurationmanager-introspec.xml
@@ -21,6 +21,7 @@
                     The available keys / parameters are:
                     <ul>
                         <li>CONFIG_ACCOUNT_ENABLE:    True or False (Default: True)</li>
+                        <li>CONFIG_ACCOUNT_RESOLVE_ONCE</li>
                         <li>CONFIG_ACCOUNT_TYPE: SIP or IAX2 (Default: SIP)</li>
                         <li>HOSTNAME: The IP adress or hostname of the registrar</li>
                         <li>USERNAME: The username (or extension) of the account</li>
@@ -446,6 +447,11 @@
        <signal name="accountsChanged" tp:name-for-bindings="accountsChanged">
        </signal>
 
+       <signal name="registrationStateChanged" tp:name-for-bindings="registrationStateChanged">
+           <arg type="s" name="accountID"/>
+           <arg type="i" name="registration_state"/>
+       </signal>
+
        <signal name="stunStatusFailure" tp:name-for_bindings="stunStatusFailure">
            <arg type="s" name="reason">
            </arg>
diff --git a/gnome/src/dbus/dbus.c b/gnome/src/dbus/dbus.c
index e68d4455913946ad8e25d0c6b42cac8a2b828a77..e2b184b3f30c67617441055784d3f8d8bc1de535 100644
--- a/gnome/src/dbus/dbus.c
+++ b/gnome/src/dbus/dbus.c
@@ -29,7 +29,10 @@
  *  shall include the source code for the parts of OpenSSL used as well
  *  as that of the covered work.
  */
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
+
 #include <glib/gi18n.h>
 #include "str_utils.h"
 #include "logger.h"
@@ -38,12 +41,12 @@
 #include "configurationmanager-glue.h"
 #include "instance-glue.h"
 #include "preferencesdialog.h"
-#include "accountlistconfigdialog.h"
 #include "mainwindow.h"
 #include "marshaller.h"
 #include "sliders.h"
 #include "statusicon.h"
 #include "assistant.h"
+#include "accountlistconfigdialog.h"
 
 #include "dbus.h"
 #include "actions.h"
@@ -422,12 +425,24 @@ record_playback_stopped_cb(DBusGProxy *proxy UNUSED, const gchar *filepath)
     update_actions();
 }
 
+static void
+registration_state_changed_cb(DBusGProxy *proxy UNUSED, const gchar *accountID,
+                              guint state, void *foo UNUSED)
+{
+    DEBUG("DBus: Registration state changed to %s for account %s",
+          account_state_name(state), accountID);
+    account_t *acc = account_list_get_by_id(accountID);
+    if (acc) {
+        acc->state = state;
+        update_account_list_status_bar(acc);
+    }
+}
+
 static void
 accounts_changed_cb(DBusGProxy *proxy UNUSED, void *foo UNUSED)
 {
     sflphone_fill_account_list();
     sflphone_fill_ip2ip_profile();
-    account_list_config_dialog_fill();
     status_bar_display_account();
     statusicon_set_tooltip();
 }
@@ -735,6 +750,11 @@ gboolean dbus_connect(GError **error)
     dbus_g_proxy_connect_signal(call_proxy, "voiceMailNotify",
                                 G_CALLBACK(voice_mail_cb), NULL, NULL);
 
+    dbus_g_proxy_add_signal(config_proxy, "registrationStateChanged", G_TYPE_STRING,
+                            G_TYPE_INT, G_TYPE_INVALID);
+    dbus_g_proxy_connect_signal(config_proxy, "registrationStateChanged",
+                                G_CALLBACK(registration_state_changed_cb), NULL, NULL);
+
     dbus_g_proxy_add_signal(call_proxy, "incomingMessage", G_TYPE_STRING,
                             G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
     dbus_g_proxy_connect_signal(call_proxy, "incomingMessage",
@@ -1076,6 +1096,7 @@ dbus_remove_account(const gchar *accountID)
 {
     GError *error = NULL;
     org_sflphone_SFLphone_ConfigurationManager_remove_account(config_proxy, accountID, &error);
+    account_list_remove(accountID);
     check_error(error);
 }
 
@@ -1093,10 +1114,10 @@ void
 dbus_add_account(account_t *a)
 {
     g_assert(a);
+    g_assert(a->accountID);
     g_assert(a->properties);
-    DEBUG("Adding %s account", a->accountID);
-    GError *error = NULL;
     g_free(a->accountID);
+    GError *error = NULL;
     a->accountID = NULL;
     org_sflphone_SFLphone_ConfigurationManager_add_account(config_proxy, a->properties, &a->accountID,
                        &error);
diff --git a/gnome/src/logger.h b/gnome/src/logger.h
index a5020c822878f9d0c1bd58adbf3dec6cf30551b3..330503be82bd3be8a2dca855d7ee087498c5c431 100644
--- a/gnome/src/logger.h
+++ b/gnome/src/logger.h
@@ -28,8 +28,8 @@
  *  as that of the covered work.
  */
 
-#ifndef __LOGGER_H
-#define __LOGGER_H
+#ifndef LOGGER_H_
+#define LOGGER_H_
 
 void internal_log (const int level, const char* format, ...);
 void set_log_level (const int level);
@@ -44,7 +44,8 @@ void set_log_level (const int level);
 #define INFO(...)      internal_log(LOG_INFO, __VA_ARGS__)
 #define DEBUG(...)     internal_log(LOG_DEBUG, __VA_ARGS__)
 
+/* Prints an error message and returns if the pointer A is NULL */
 #define RETURN_IF_NULL(A, M, ...) \
-    if ((A) == NULL) { ERROR(M, ##__VA_ARGS__); return; }
+    if (!(A)) { ERROR(M, ##__VA_ARGS__); return; }
 
-#endif
+#endif // LOGGER_H_
diff --git a/gnome/src/main.c b/gnome/src/main.c
index 8590e276f6f648721bd0e316c65d7e34fd9c1a84..c6dc14ab2ea85938be3a701f0ff43a51790027a9 100644
--- a/gnome/src/main.c
+++ b/gnome/src/main.c
@@ -112,7 +112,6 @@ main(int argc, char *argv[])
         set_minimized(TRUE);
     }
 
-
     status_bar_display_account();
 
     sflphone_fill_history();
diff --git a/gnome/src/uimanager.c b/gnome/src/uimanager.c
index 25a45352eb320f218dae3bfb50d7b45990c07bce..b2b16d5d2ef0b42687a0e2d0130a300161348942 100644
--- a/gnome/src/uimanager.c
+++ b/gnome/src/uimanager.c
@@ -67,29 +67,33 @@ void show_edit_number(callable_obj_t *call);
 
 static GtkWidget *toolbar_;
 
-static guint transferButtonConnId_; // The button toggled signal connection ID
-static guint recordButtonConnId_; // The button toggled signal connection ID
+// store the signal ID in case we need to
+// intercept this signal
+static guint transferButtonConnId_;
+static guint recordButtonConnId_;
 
 static GtkAction * pickUpAction_;
-static GtkWidget * pickUpWidget_;
 static GtkAction * newCallAction_;
-static GtkWidget * newCallWidget_;
 static GtkAction * hangUpAction_;
+static GtkAction * copyAction_;
+static GtkAction * pasteAction_;
+static GtkAction * recordAction_;
+static GtkAction * muteAction_;
+static GtkAction * voicemailAction_;
+static GtkAction * imAction_;
+
+static GtkWidget * pickUpWidget_;
+static GtkWidget * newCallWidget_;
 static GtkWidget * hangUpWidget_;
 static GtkWidget * holdMenu_;
 static GtkWidget * holdToolbar_;
 static GtkWidget * offHoldToolbar_;
 static GtkWidget * transferToolbar_;
-static GtkAction * copyAction_;
-static GtkAction * pasteAction_;
-static GtkAction * recordAction_;
-static GtkAction * muteAction_;
 static GtkWidget * recordWidget_;
 static GtkWidget * muteWidget_;
-static GtkAction * voicemailAction_;
 static GtkWidget * voicemailToolbar_;
 static GtkWidget * imToolbar_;
-static GtkAction * imAction_;
+
 static GtkWidget * playRecordWidget_;
 static GtkWidget * stopRecordWidget_;
 
@@ -130,69 +134,332 @@ call_mute(void)
     sflphone_mute_call();
 }
 
+
+static void
+update_toolbar_for_call(callable_obj_t *selectedCall, gboolean instant_messaging_enabled) {
+    int pos = 0;
+
+    DEBUG("UIManager: Update actions for call %s", selectedCall->_callID);
+
+    if(selectedCall == NULL) {
+        ERROR("Selected call is NULL while updating toolbar");
+        return;
+    }
+
+    // update icon in systray
+    show_status_hangup_icon();
+
+    gtk_action_set_sensitive(copyAction_, TRUE);
+
+    switch (selectedCall->_state) {
+        case CALL_STATE_INCOMING:
+        {
+                DEBUG("UIManager: Call State Incoming");
+                // Make the button toolbar clickable
+                gtk_action_set_sensitive(pickUpAction_, TRUE);
+                gtk_action_set_sensitive(hangUpAction_, TRUE);
+                gtk_action_set_sensitive(muteAction_, TRUE);
+                // Replace the dial button with the hangup button
+                g_object_ref(newCallWidget_);
+                remove_from_toolbar(newCallWidget_);
+                pos = 0;
+                add_to_toolbar(toolbar_, pickUpWidget_, pos++);
+                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
+                add_to_toolbar(toolbar_, muteWidget_, pos++);
+                break;
+        }
+        case CALL_STATE_HOLD:
+        {
+                DEBUG("UIManager: Call State Hold");
+                gtk_action_set_sensitive(hangUpAction_, TRUE);
+                gtk_widget_set_sensitive(holdMenu_, TRUE);
+                gtk_widget_set_sensitive(offHoldToolbar_, TRUE);
+                gtk_widget_set_sensitive(newCallWidget_, TRUE);
+
+                // Replace the hold button with the off-hold button
+                pos = 1;
+                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
+                add_to_toolbar(toolbar_, offHoldToolbar_, pos++);
+
+                if (instant_messaging_enabled) {
+                    gtk_action_set_sensitive(imAction_, TRUE);
+                    add_to_toolbar(toolbar_, imToolbar_, pos++);
+                }
+
+                break;
+        }
+        case CALL_STATE_RINGING:
+        {
+                DEBUG("UIManager: Call State Ringing");
+                gtk_action_set_sensitive(pickUpAction_, TRUE);
+                gtk_action_set_sensitive(hangUpAction_, TRUE);
+                pos = 1;
+                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
+                add_to_toolbar(toolbar_, muteWidget_, pos++);
+                break;
+        }
+        case CALL_STATE_DIALING:
+        {
+                DEBUG("UIManager: Call State Dialing");
+                gtk_action_set_sensitive(pickUpAction_, TRUE);
+
+                if (active_calltree_tab == current_calls_tab)
+                    gtk_action_set_sensitive(hangUpAction_, TRUE);
+
+                g_object_ref(newCallWidget_);
+                remove_from_toolbar(newCallWidget_);
+                pos = 0;
+                add_to_toolbar(toolbar_, pickUpWidget_, pos++);
+
+                if (active_calltree_tab == current_calls_tab)
+                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
+                else if (active_calltree_tab == history_tab) {
+                    if (is_non_empty(selectedCall->_recordfile)) {
+                        if (selectedCall->_record_is_playing)
+                            add_to_toolbar(toolbar_, stopRecordWidget_, pos++);
+                        else
+                            add_to_toolbar(toolbar_, playRecordWidget_, pos++);
+                    }
+                }
+                break;
+        }
+        case CALL_STATE_CURRENT:
+        {
+                DEBUG("UIManager: Call State Current");
+                gtk_action_set_sensitive(hangUpAction_, TRUE);
+                gtk_action_set_sensitive(recordAction_, TRUE);
+                gtk_action_set_sensitive(muteAction_, TRUE);
+                gtk_widget_set_sensitive(holdMenu_, TRUE);
+                gtk_widget_set_sensitive(holdToolbar_, TRUE);
+                gtk_widget_set_sensitive(transferToolbar_, TRUE);
+                gtk_widget_set_sensitive(muteWidget_, TRUE);
+                if (instant_messaging_enabled)
+                    gtk_action_set_sensitive(imAction_, TRUE);
+
+                pos = 1;
+                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
+                add_to_toolbar(toolbar_, holdToolbar_, pos++);
+                add_to_toolbar(toolbar_, transferToolbar_, pos++);
+                add_to_toolbar(toolbar_, recordWidget_, pos++);
+                add_to_toolbar(toolbar_, muteWidget_, pos++);
+                if (instant_messaging_enabled) {
+                    add_to_toolbar(toolbar_, imToolbar_, pos++);
+
+                g_signal_handler_block(transferToolbar_, transferButtonConnId_);
+                gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE);
+                g_signal_handler_unblock(transferToolbar_, transferButtonConnId_);
+                g_signal_handler_block(recordWidget_, recordButtonConnId_);
+                gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), FALSE);
+                g_signal_handler_unblock(recordWidget_, recordButtonConnId_);
+                break;
+        }
+
+        case CALL_STATE_RECORD:
+        {
+                DEBUG("UIManager: Call State Record");
+                gtk_action_set_sensitive(hangUpAction_, TRUE);
+                gtk_action_set_sensitive(recordAction_, TRUE);
+                gtk_action_set_sensitive(muteAction_, TRUE);
+                gtk_widget_set_sensitive(holdMenu_, TRUE);
+                gtk_widget_set_sensitive(holdToolbar_, TRUE);
+                gtk_widget_set_sensitive(transferToolbar_, TRUE);
+                gtk_widget_set_sensitive(muteWidget_, TRUE);
+                if (instant_messaging_enabled)
+                    gtk_action_set_sensitive(imAction_, TRUE);
+
+                pos = 1;
+                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
+                add_to_toolbar(toolbar_, holdToolbar_, pos++);
+                add_to_toolbar(toolbar_, transferToolbar_, pos++);
+                add_to_toolbar(toolbar_, recordWidget_, pos++);
+                add_to_toolbar(toolbar_, muteWidget_, pos++);
+                if (instant_messaging_enabled)
+                    add_to_toolbar(toolbar_, imToolbar_, pos++);
+
+                g_signal_handler_block(transferToolbar_, transferButtonConnId_);
+                gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE);
+                g_signal_handler_unblock(transferToolbar_, transferButtonConnId_);
+                g_signal_handler_block(recordWidget_, recordButtonConnId_);
+                gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), TRUE);
+                g_signal_handler_unblock(recordWidget_, recordButtonConnId_);
+                break;
+        }
+        case CALL_STATE_BUSY:
+        case CALL_STATE_FAILURE:
+        {
+                pos = 1;
+                DEBUG("UIManager: Call State Busy/Failure");
+                gtk_action_set_sensitive(hangUpAction_, TRUE);
+                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
+                break;
+        }
+        case CALL_STATE_TRANSFER:
+        {
+                pos = 1;
+                gtk_action_set_sensitive(hangUpAction_, TRUE);
+                gtk_action_set_sensitive(muteAction_, TRUE);
+                gtk_widget_set_sensitive(holdMenu_, TRUE);
+                gtk_widget_set_sensitive(holdToolbar_, TRUE);
+                gtk_widget_set_sensitive(transferToolbar_, TRUE);
+                gtk_widget_set_sensitive(transferToolbar_, TRUE);
+                gtk_widget_set_sensitive(muteWidget_, TRUE);
+
+                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
+                add_to_toolbar(toolbar_, transferToolbar_, pos++);
+                g_signal_handler_block(transferToolbar_, transferButtonConnId_);
+                gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), TRUE);
+                g_signal_handler_unblock(transferToolbar_, transferButtonConnId_);
+                add_to_toolbar(toolbar_, muteWidget_, pos++);
+                break;
+        }
+        default:
+            ERROR("UIMAnager: Error: Unknown state in action update!");
+            break;
+        }
+    }
+}
+
+static void
+update_toolbar_for_conference(conference_obj_t * selectedConf, gboolean instant_messaging_enabled) {
+    int pos = 0;
+
+    DEBUG("UIManager: Update actions for conference");
+
+    // update icon in systray
+    show_status_hangup_icon();
+
+    switch (selectedConf->_state) {
+
+        case CONFERENCE_STATE_ACTIVE_ATTACHED:
+        case CONFERENCE_STATE_ACTIVE_DETACHED:
+            DEBUG("UIManager: Conference State Active");
+
+            if (active_calltree_tab == current_calls_tab) {
+                gtk_action_set_sensitive(hangUpAction_, TRUE);
+                gtk_widget_set_sensitive(holdToolbar_, TRUE);
+                gtk_action_set_sensitive(recordAction_, TRUE);
+                pos = 1;
+                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
+                add_to_toolbar(toolbar_, holdToolbar_, pos++);
+                add_to_toolbar(toolbar_, recordWidget_, pos++);
+
+                if (instant_messaging_enabled) {
+                    gtk_action_set_sensitive(imAction_, TRUE);
+                    add_to_toolbar(toolbar_, imToolbar_, pos);
+                }
+            } else if (active_calltree_tab == history_tab) {
+                if (is_non_empty(selectedConf->_recordfile)) {
+                    pos = 2;
+                    if (selectedConf->_record_is_playing)
+                        add_to_toolbar(toolbar_, stopRecordWidget_, pos);
+                    else
+                        add_to_toolbar(toolbar_, playRecordWidget_, pos);
+                }
+            }
+
+            break;
+        case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD:
+        case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD: {
+            pos = 1;
+            DEBUG("UIManager: Conference State Record");
+            gtk_action_set_sensitive(hangUpAction_, TRUE);
+            gtk_widget_set_sensitive(holdToolbar_, TRUE);
+            gtk_action_set_sensitive(recordAction_, TRUE);
+            add_to_toolbar(toolbar_, hangUpWidget_, pos++);
+            add_to_toolbar(toolbar_, holdToolbar_, pos++);
+            add_to_toolbar(toolbar_, recordWidget_, pos++);
+
+            if (instant_messaging_enabled) {
+                gtk_action_set_sensitive(imAction_, TRUE);
+                add_to_toolbar(toolbar_, imToolbar_, pos);
+            }
+
+            break;
+        }
+        case CONFERENCE_STATE_HOLD:
+        case CONFERENCE_STATE_HOLD_RECORD: {
+            DEBUG("UIManager: Conference State Hold");
+            pos = 1;
+            gtk_action_set_sensitive(hangUpAction_, TRUE);
+            gtk_widget_set_sensitive(offHoldToolbar_, TRUE);
+            gtk_action_set_sensitive(recordAction_, TRUE);
+            add_to_toolbar(toolbar_, hangUpWidget_, pos++);
+            add_to_toolbar(toolbar_, offHoldToolbar_, pos++);
+            add_to_toolbar(toolbar_, recordWidget_, pos++);
+
+            if (instant_messaging_enabled) {
+                gtk_action_set_sensitive(imAction_, TRUE);
+                add_to_toolbar(toolbar_, imToolbar_, pos);
+            }
+
+            break;
+        }
+        default:
+            WARN("UIManager: Error: Should not happen in action update!");
+            break;
+    }
+
+}
+
 void
 update_actions()
 {
-    int pos = 0;
-
     gtk_action_set_sensitive(newCallAction_, TRUE);
     gtk_action_set_sensitive(pickUpAction_, FALSE);
     gtk_action_set_sensitive(hangUpAction_, FALSE);
+    gtk_action_set_sensitive(recordAction_, FALSE);
+    gtk_action_set_sensitive(muteAction_, FALSE);
+    gtk_action_set_sensitive(copyAction_, FALSE);
     gtk_action_set_sensitive(imAction_, FALSE);
 
+    gtk_widget_set_sensitive(holdMenu_, FALSE);
+    gtk_widget_set_sensitive(holdToolbar_, FALSE);
+    gtk_widget_set_sensitive(offHoldToolbar_, FALSE);
+    gtk_widget_set_sensitive(recordWidget_, FALSE);
+    gtk_widget_set_sensitive(muteWidget_, FALSE);
+    gtk_widget_set_sensitive(historyButton_, FALSE);
+
+    // Increment the reference counter
     g_object_ref(hangUpWidget_);
     g_object_ref(recordWidget_);
     g_object_ref(muteWidget_);
     g_object_ref(holdToolbar_);
     g_object_ref(offHoldToolbar_);
-
-    if (addrbook)
-        g_object_ref(contactButton_);
-
     g_object_ref(historyButton_);
     g_object_ref(transferToolbar_);
     g_object_ref(voicemailToolbar_);
     g_object_ref(imToolbar_);
 
+    if (addrbook)
+        g_object_ref(contactButton_);
+
+    // Make sure the toolbar is reinitialized
+    // Widget will be added according to the state
+    // of the selected call
     remove_from_toolbar(hangUpWidget_);
     remove_from_toolbar(recordWidget_);
     remove_from_toolbar(muteWidget_);
     remove_from_toolbar(transferToolbar_);
     remove_from_toolbar(historyButton_);
-
-    if (addrbook)
-        remove_from_toolbar(contactButton_);
-
     remove_from_toolbar(voicemailToolbar_);
     remove_from_toolbar(imToolbar_);
-
-    gtk_widget_set_sensitive(holdMenu_, FALSE);
-    gtk_widget_set_sensitive(holdToolbar_, FALSE);
-    gtk_widget_set_sensitive(offHoldToolbar_, FALSE);
-    gtk_action_set_sensitive(recordAction_, FALSE);
-    gtk_action_set_sensitive(muteAction_, FALSE);
-    gtk_widget_set_sensitive(recordWidget_, FALSE);
-    gtk_widget_set_sensitive(muteWidget_, FALSE);
-    gtk_action_set_sensitive(copyAction_, FALSE);
-
-    if (addrbook)
-        gtk_widget_set_sensitive(contactButton_, FALSE);
-
-    gtk_widget_set_sensitive(historyButton_, FALSE);
-
-    if (addrbook)
-        gtk_widget_set_tooltip_text(contactButton_, _("No address book selected"));
-
     remove_from_toolbar(holdToolbar_);
     remove_from_toolbar(offHoldToolbar_);
     remove_from_toolbar(newCallWidget_);
     remove_from_toolbar(pickUpWidget_);
-
-    add_to_toolbar(toolbar_, newCallWidget_, 0);
-
     remove_from_toolbar(playRecordWidget_);
     remove_from_toolbar(stopRecordWidget_);
 
+    if (addrbook) {
+        remove_from_toolbar(contactButton_);
+        gtk_widget_set_sensitive(contactButton_, FALSE);
+        gtk_widget_set_tooltip_text(contactButton_, _("No address book selected"));
+    }
+
+    // New call widget always present
+    add_to_toolbar(toolbar_, newCallWidget_, 0);
+
+    // Add the history button and set it to sensitive if enabled
     if (eel_gconf_get_integer(HISTORY_ENABLED)) {
         add_to_toolbar(toolbar_, historyButton_, -1);
         gtk_widget_set_sensitive(historyButton_, TRUE);
@@ -200,9 +467,7 @@ update_actions()
 
     GtkToolItem *separator = gtk_separator_tool_item_new();
     gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), separator, -1);
-    // add mute button
-    add_to_toolbar(toolbar_, muteWidget_, -1);
-    gtk_action_set_sensitive(muteAction_, TRUE);
+
 
     // If addressbook support has been enabled and all addressbooks are loaded, display the icon
     if (addrbook && addrbook->is_ready() && addressbook_config_load_parameters()->enable) {
@@ -224,242 +489,9 @@ update_actions()
         instant_messaging_enabled = eel_gconf_get_integer(INSTANT_MESSAGING_ENABLED);
 
     if (selectedCall) {
-        DEBUG("UIManager: Update actions for call %s", selectedCall->_callID);
-
-        // update icon in systray
-        show_status_hangup_icon();
-
-        gtk_action_set_sensitive(copyAction_, TRUE);
-
-        switch (selectedCall->_state) {
-            case CALL_STATE_INCOMING:
-                {
-                    DEBUG("UIManager: Call State Incoming");
-                    // Make the button toolbar clickable
-                    gtk_action_set_sensitive(pickUpAction_, TRUE);
-                    gtk_action_set_sensitive(hangUpAction_, TRUE);
-                    // Replace the dial button with the hangup button
-                    g_object_ref(newCallWidget_);
-                    remove_from_toolbar(newCallWidget_);
-                    pos = 0;
-                    add_to_toolbar(toolbar_, pickUpWidget_, pos++);
-                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
-                    break;
-                }
-            case CALL_STATE_HOLD:
-                {
-                    DEBUG("UIManager: Call State Hold");
-                    gtk_action_set_sensitive(hangUpAction_, TRUE);
-                    gtk_widget_set_sensitive(holdMenu_, TRUE);
-                    gtk_widget_set_sensitive(offHoldToolbar_, TRUE);
-                    gtk_widget_set_sensitive(newCallWidget_, TRUE);
-
-                    // Replace the hold button with the off-hold button
-                    pos = 1;
-                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
-                    add_to_toolbar(toolbar_, offHoldToolbar_, pos++);
-
-                    if (instant_messaging_enabled) {
-                        gtk_action_set_sensitive(imAction_, TRUE);
-                        add_to_toolbar(toolbar_, imToolbar_, pos++);
-                    }
-
-                    break;
-                }
-            case CALL_STATE_RINGING:
-                {
-                    DEBUG("UIManager: Call State Ringing");
-                    gtk_action_set_sensitive(pickUpAction_, TRUE);
-                    gtk_action_set_sensitive(hangUpAction_, TRUE);
-                    pos = 1;
-                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
-                    break;
-                }
-            case CALL_STATE_DIALING:
-                {
-                    DEBUG("UIManager: Call State Dialing");
-                    gtk_action_set_sensitive(pickUpAction_, TRUE);
-
-                    if (active_calltree_tab == current_calls_tab)
-                        gtk_action_set_sensitive(hangUpAction_, TRUE);
-
-                    g_object_ref(newCallWidget_);
-                    remove_from_toolbar(newCallWidget_);
-                    pos = 0;
-                    add_to_toolbar(toolbar_, pickUpWidget_, pos++);
-
-                    if (active_calltree_tab == current_calls_tab)
-                        add_to_toolbar(toolbar_, hangUpWidget_, pos++);
-                    else if (active_calltree_tab == history_tab) {
-                        if (is_non_empty(selectedCall->_recordfile)) {
-                            if (selectedCall->_record_is_playing)
-                                add_to_toolbar(toolbar_, stopRecordWidget_, pos++);
-                            else
-                                add_to_toolbar(toolbar_, playRecordWidget_, pos++);
-                        }
-                    }
-                    break;
-                }
-            case CALL_STATE_CURRENT:
-                {
-                    DEBUG("UIManager: Call State Current");
-                    gtk_action_set_sensitive(hangUpAction_, TRUE);
-                    pos = 1;
-                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
-                    gtk_widget_set_sensitive(holdMenu_, TRUE);
-                    gtk_widget_set_sensitive(holdToolbar_, TRUE);
-                    gtk_widget_set_sensitive(transferToolbar_, TRUE);
-                    gtk_action_set_sensitive(recordAction_, TRUE);
-                    add_to_toolbar(toolbar_, holdToolbar_, pos++);
-                    add_to_toolbar(toolbar_, transferToolbar_, pos++);
-                    add_to_toolbar(toolbar_, recordWidget_, pos++);
-                    g_signal_handler_block(transferToolbar_, transferButtonConnId_);
-                    gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE);
-                    g_signal_handler_unblock(transferToolbar_, transferButtonConnId_);
-                    g_signal_handler_block(recordWidget_, recordButtonConnId_);
-                    gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), FALSE);
-                    g_signal_handler_unblock(recordWidget_, recordButtonConnId_);
-
-                    if (instant_messaging_enabled) {
-                        gtk_action_set_sensitive(imAction_, TRUE);
-                        add_to_toolbar(toolbar_, imToolbar_, pos++);
-                    }
-
-                    break;
-                }
-
-            case CALL_STATE_RECORD:
-                {
-                    DEBUG("UIManager: Call State Record");
-                    pos = 1;
-                    gtk_action_set_sensitive(hangUpAction_, TRUE);
-                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
-                    gtk_widget_set_sensitive(holdMenu_, TRUE);
-                    gtk_widget_set_sensitive(holdToolbar_, TRUE);
-                    gtk_widget_set_sensitive(transferToolbar_, TRUE);
-                    gtk_action_set_sensitive(recordAction_, TRUE);
-                    add_to_toolbar(toolbar_, holdToolbar_, pos++);
-                    add_to_toolbar(toolbar_, transferToolbar_, pos++);
-                    add_to_toolbar(toolbar_, recordWidget_, pos++);
-                    g_signal_handler_block(transferToolbar_, transferButtonConnId_);
-                    gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE);
-                    g_signal_handler_unblock(transferToolbar_, transferButtonConnId_);
-                    g_signal_handler_block(recordWidget_, recordButtonConnId_);
-                    gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), TRUE);
-                    g_signal_handler_unblock(recordWidget_, recordButtonConnId_);
-
-                    if (instant_messaging_enabled) {
-                        gtk_action_set_sensitive(imAction_, TRUE);
-                        add_to_toolbar(toolbar_, imToolbar_, pos++);
-                    }
-
-                    break;
-                }
-            case CALL_STATE_BUSY:
-            case CALL_STATE_FAILURE:
-                {
-                    pos = 1;
-                    DEBUG("UIManager: Call State Busy/Failure");
-                    gtk_action_set_sensitive(hangUpAction_, TRUE);
-                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
-                    break;
-                }
-            case CALL_STATE_TRANSFER:
-                {
-                    pos = 1;
-                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
-                    add_to_toolbar(toolbar_, transferToolbar_, pos++);
-                    g_signal_handler_block(transferToolbar_, transferButtonConnId_);
-                    gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), TRUE);
-                    g_signal_handler_unblock(transferToolbar_, transferButtonConnId_);
-                    gtk_action_set_sensitive(hangUpAction_, TRUE);
-                    gtk_widget_set_sensitive(holdMenu_, TRUE);
-                    gtk_widget_set_sensitive(holdToolbar_, TRUE);
-                    gtk_widget_set_sensitive(transferToolbar_, TRUE);
-                    break;
-                }
-            default:
-                ERROR("UIMAnager: Error: Unknown state in action update!");
-                break;
-        }
-
+        update_toolbar_for_call(selectedCall, instant_messaging_enabled);
     } else if (selectedConf) {
-
-        DEBUG("UIManager: Update actions for conference");
-
-        // update icon in systray
-        show_status_hangup_icon();
-
-        switch (selectedConf->_state) {
-
-            case CONFERENCE_STATE_ACTIVE_ATTACHED:
-            case CONFERENCE_STATE_ACTIVE_DETACHED:
-                DEBUG("UIManager: Conference State Active");
-
-                if (active_calltree_tab == current_calls_tab) {
-                    gtk_action_set_sensitive(hangUpAction_, TRUE);
-                    gtk_widget_set_sensitive(holdToolbar_, TRUE);
-                    gtk_action_set_sensitive(recordAction_, TRUE);
-                    pos = 1;
-                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
-                    add_to_toolbar(toolbar_, holdToolbar_, pos++);
-                    add_to_toolbar(toolbar_, recordWidget_, pos++);
-
-                    if (instant_messaging_enabled) {
-                        gtk_action_set_sensitive(imAction_, TRUE);
-                        add_to_toolbar(toolbar_, imToolbar_, pos);
-                    }
-                } else if (active_calltree_tab == history_tab) {
-                    if (is_non_empty(selectedConf->_recordfile)) {
-                        pos = 2;
-                        if (selectedConf->_record_is_playing)
-                            add_to_toolbar(toolbar_, stopRecordWidget_, pos);
-                        else
-                            add_to_toolbar(toolbar_, playRecordWidget_, pos);
-                    }
-                }
-
-                break;
-            case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD:
-            case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD: {
-                pos = 1;
-                DEBUG("UIManager: Conference State Record");
-                gtk_action_set_sensitive(hangUpAction_, TRUE);
-                gtk_widget_set_sensitive(holdToolbar_, TRUE);
-                gtk_action_set_sensitive(recordAction_, TRUE);
-                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
-                add_to_toolbar(toolbar_, holdToolbar_, pos++);
-                add_to_toolbar(toolbar_, recordWidget_, pos++);
-
-                if (instant_messaging_enabled) {
-                    gtk_action_set_sensitive(imAction_, TRUE);
-                    add_to_toolbar(toolbar_, imToolbar_, pos);
-                }
-
-                break;
-            }
-            case CONFERENCE_STATE_HOLD:
-            case CONFERENCE_STATE_HOLD_RECORD: {
-                DEBUG("UIManager: Conference State Hold");
-                pos = 1;
-                gtk_action_set_sensitive(hangUpAction_, TRUE);
-                gtk_widget_set_sensitive(offHoldToolbar_, TRUE);
-                gtk_action_set_sensitive(recordAction_, TRUE);
-                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
-                add_to_toolbar(toolbar_, offHoldToolbar_, pos++);
-                add_to_toolbar(toolbar_, recordWidget_, pos++);
-
-                if (instant_messaging_enabled) {
-                    gtk_action_set_sensitive(imAction_, TRUE);
-                    add_to_toolbar(toolbar_, imToolbar_, pos);
-                }
-
-                break;
-            }
-            default:
-                WARN("UIManager: Error: Should not happen in action update!");
-                break;
-        }
+        update_toolbar_for_conference(selectedConf, instant_messaging_enabled);
     } else {
         // update icon in systray
         hide_status_hangup_icon();
@@ -554,7 +586,7 @@ help_about(void * foo UNUSED)
             "artists", artists,
             "authors", authors,
             "comments", _("SFLphone is a VoIP client compatible with SIP and IAX2 protocols."),
-            "copyright", "Copyright © 2004-2011 Savoir-faire Linux Inc.",
+            "copyright", "Copyright © 2004-2012 Savoir-faire Linux Inc.",
             "name", PACKAGE,
             "title", _("About SFLphone"),
             "version", VERSION,