diff --git a/src/api/call.h b/src/api/call.h
index 3a2edec2a2ae1ce5f8bc505fc3c372e79335a3c7..b05d320b31ada3750184a0ab7b0ff2feb2d80d1e 100644
--- a/src/api/call.h
+++ b/src/api/call.h
@@ -21,6 +21,7 @@
 // std
 #include <string>
 #include <ctime>
+#include <chrono>
 
 // Qt
 #include <QObject>
@@ -87,11 +88,38 @@ to_string(const call::Status& status)
     }
 }
 
+/**
+ * Convert status from daemon into a Status
+ * @warning status is a string from the daemon, not from to_string()
+ * @param  status
+ * @return
+ */
+static const Status
+to_status(const std::string& status)
+{
+    if (status == "INCOMING")
+        return Status::INCOMING_RINGING;
+    else if (status == "CONNECTING")
+        return Status::CONNECTING;
+    else if (status == "RINGING")
+        return Status::OUTGOING_RINGING;
+    else if (status == "HUNGUP")
+        return Status::TERMINATING;
+    else if (status == "HOLD")
+        return Status::PAUSED;
+    else if (status == "UNHOLD" || status == "CURRENT")
+        return Status::IN_PROGRESS;
+    else if (status == "INACTIVE" || status == "BUSY")
+        return Status::INACTIVE;
+    else if (status == "OVER" || status == "FAILURE")
+        return Status::ENDED;
+    return Status::INVALID;
+}
 
 struct Info
 {
     std::string id;
-    std::time_t startTime = 0;
+    std::chrono::steady_clock::time_point startTime;
     Status status = Status::INVALID;
     std::string peer;
     bool audioMuted = false;
diff --git a/src/api/newcallmodel.h b/src/api/newcallmodel.h
index ae79c135d26c466b2c997408b5a1ad0903c85c17..ec6bd2c4bc9edb20b7b50f2900f321c3daa42854 100644
--- a/src/api/newcallmodel.h
+++ b/src/api/newcallmodel.h
@@ -26,9 +26,18 @@
 // Qt
 #include <qobject.h>
 
+// Data
+#include "api/call.h"
+#include "api/account.h"
+
+namespace Video {
+class Renderer;
+}
+
 namespace lrc
 {
 
+class CallbacksHandler;
 class NewCallModelPimpl;
 
 namespace api
@@ -38,8 +47,12 @@ namespace account { struct Info; }
 namespace call { struct Info; }
 class NewAccountModel;
 
+/**
+  *  @brief Class that manages call informations.
+  */
 class NewCallModel : public QObject {
     Q_OBJECT
+
 public:
     using CallInfoMap = std::map<std::string, std::shared_ptr<call::Info>>;
 
@@ -51,20 +64,131 @@ public:
         VIDEO
     };
 
-    NewCallModel(const account::Info& owner);
+    NewCallModel(const account::Info& owner, const CallbacksHandler& callbacksHandler);
     ~NewCallModel();
 
-    const call::Info& createCall(const std::string& contactUri);
+    /**
+     * Create a new call with a contact
+     * @param  url of the contact to call
+     * @return the call uid created
+     */
+    std::string createCall(const std::string& url);
+    /**
+     * Get the call from its call id
+     * @param  uid
+     * @return the callInfo
+     * @throw out_of_range exception if not found
+     */
+    const call::Info& getCall(const std::string& uid) const;
+    /**
+     * Get the call from the peer uri
+     * @param  uri
+     * @return the callInfo
+     * @throw out_of_range exception if not found
+     */
     const call::Info& getCallFromURI(const std::string& uri) const;
+    /**
+     * @param  callId to test
+     * @return true if callId is presend else false.
+     */
+    bool hasCall(const std::string& callId);
+    /**
+     * Send a text message to a SIP call
+     * @param callId
+     * @param body of the message
+     */
+    void sendSipMessage(const std::string& callId, const std::string& body) const;
 
+    /**
+     * Accept a call
+     * @param callId
+     */
+    void accept(const std::string& callId) const;
+    /**
+     * Hang up a call
+     * @param callId
+     */
     void hangUp(const std::string& callId) const;
+    /**
+     * Toggle audio record on a call
+     * @param callId
+     */
+    void toggleAudioRecord(const std::string& callId) const;
+    /**
+     * Play DTMF in a call
+     * @param callId
+     * @param value to play
+     */
+    void playDTMF(const std::string& callId, const std::string& value) const;
+    /**
+     * Toggle pause on a call
+     * @param callId
+     */
     void togglePause(const std::string& callId) const;
-    void toggleMedia(const std::string& callId, const Media media) const;
-    void toggleRecoringdAudio(const std::string& callId) const;
+    /**
+     * Toggle a media on a call
+     * @param callId
+     * @param media {AUDIO, VIDEO}
+     * @param flag is muted
+     */
+    void toggleMedia(const std::string& callId, const NewCallModel::Media media, bool flag) const;
+    /**
+     * Not implemented yet
+     */
     void setQuality(const std::string& callId, const double quality) const;
+    /**
+     * Not implemented yet
+     */
     void transfer(const std::string& callId, const std::string& to) const;
-    void addParticipant(const std::string& callId, const std::string& participant);
-    void removeParticipant(const std::string& callId, const std::string& participant);
+    /**
+     * Not implemented yet
+     */
+    void addParticipant(const std::string& callId, const std::string& participant) const;
+    /**
+     * Not implemented yet
+     */
+    void removeParticipant(const std::string& callId, const std::string& participant) const;
+
+    /**
+     * @param  callId
+     * @return the renderer linked to a call
+     */
+    Video::Renderer* getRenderer(const std::string& callId) const;
+
+    /**
+     * @param  callId
+     * @return a human readable call duration (M:ss)
+     */
+    std::string getFormattedCallDuration(const std::string& callId) const;
+
+Q_SIGNALS:
+    /**
+     * Emitted when a call state changes
+     * @param callId
+     */
+    void callStatusChanged(const std::string& callId) const;
+    /**
+     * Emitted when a call starts
+     * @param callId
+     */
+    void callStarted(const std::string& callId) const;
+    /**
+     * Emitted when a call is over
+     * @param callId
+     */
+    void callEnded(const std::string& callId) const;
+    /**
+     * Emitted when a call is incoming
+     * @param callId
+     * @param fromId the peer uri
+     */
+    void newIncomingCall(const std::string& callId, const std::string& fromId) const;
+    /**
+     * Emitted when the renderer starts
+     * @param callId
+     * @param renderer
+     */
+    void remotePreviewStarted(const std::string& callId, Video::Renderer* renderer) const;
 
 private:
     std::unique_ptr<NewCallModelPimpl> pimpl_;
diff --git a/src/contactmodel.cpp b/src/contactmodel.cpp
index 03fbdc2c1b87842e7a2d32aea8cfa165a7fbce12..dbadc19d3a0af0a92532eaedd08a91377346e635 100644
--- a/src/contactmodel.cpp
+++ b/src/contactmodel.cpp
@@ -344,6 +344,8 @@ ContactModelPimpl::ContactModelPimpl(const ContactModel& linked,
             this, &ContactModelPimpl::slotIncomingContactRequest);
     connect(&callbacksHandler, &CallbacksHandler::registeredNameFound,
             this, &ContactModelPimpl::slotRegisteredNameFound);
+    connect(&*linked.owner.callModel, &NewCallModel::newIncomingCall,
+            this, &ContactModelPimpl::slotIncomingCall);
     connect(&callbacksHandler, &lrc::CallbacksHandler::newAccountMessage,
             this, &ContactModelPimpl::slotNewAccountMessage);
 
diff --git a/src/conversationmodel.cpp b/src/conversationmodel.cpp
index 2e5d3b89c77a233b461bd6bdd33dc37b3a4effd4..543c872790e1726289c5119a5b8122a91633bc93 100644
--- a/src/conversationmodel.cpp
+++ b/src/conversationmodel.cpp
@@ -266,7 +266,38 @@ ConversationModel::selectConversation(const std::string& uid) const
         return;
     }
 
-    // fully functional behaviour not implemented in this patch
+    auto& conversation = pimpl_->conversations.at(conversationIdx);
+    try  {
+        auto call = owner.callModel->getCall(conversation.callId);
+        switch (call.status) {
+            case call::Status::INCOMING_RINGING:
+            case call::Status::OUTGOING_RINGING:
+            case call::Status::CONNECTING:
+            case call::Status::SEARCHING:
+                // We are currently in a call
+                // TODO fully functional behaviour not implemented in this patch
+                break;
+            case call::Status::PAUSED:
+            case call::Status::PEER_PAUSED:
+            case call::Status::CONNECTED:
+            case call::Status::IN_PROGRESS:
+                // We are currently receiving a call
+                // TODO fully functional behaviour not implemented in this patch
+                break;
+            case call::Status::INVALID:
+            case call::Status::OUTGOING_REQUESTED:
+            case call::Status::INACTIVE:
+            case call::Status::ENDED:
+            case call::Status::TERMINATING:
+            case call::Status::AUTO_ANSWERING:
+            default:
+                // We are not in a call, show the chatview
+                // TODO fully functional behaviour not implemented in this patch
+                break;
+        }
+    } catch (const std::out_of_range&) {
+        // TODO fully functional behaviour not implemented in this patch
+    }
 }
 
 void
@@ -316,7 +347,7 @@ ConversationModel::placeCall(const std::string& uid)
     if (owner.profileInfo.type != profile::Type::SIP) {
         url = "ring:" + url; // Add the ring: before or it will fail.
     }
-    // at this point we are not yet ready to do a call
+    conversation.callId = owner.callModel->createCall(url);
     if (convId.empty()) {
         // The conversation has changed because it was with the temporary item
         auto contactProfileId = database::getProfileId(pimpl_->db, contactInfo.profileInfo.uri);
@@ -356,7 +387,7 @@ ConversationModel::sendMessage(const std::string& uid, const std::string& body)
         auto contactInfo = owner.contactModel->getContact(participant);
         pimpl_->sendContactRequest(participant);
         if (not conversation.callId.empty())
-            true; // requires more work in NewCallModel to send message from this point
+            owner.callModel->sendSipMessage(conversation.callId, body);
         else
             owner.contactModel->sendDhtMessage(contactInfo.profileInfo.uri, body);
         if (convId.empty()) {
@@ -457,6 +488,25 @@ ConversationModelPimpl::ConversationModelPimpl(const ConversationModel& linked,
             this, &ConversationModelPimpl::slotNewAccountMessage);
     connect(&callbacksHandler, &CallbacksHandler::incomingCallMessage,
             this, &ConversationModelPimpl::slotIncomingCallMessage);
+
+
+    // Call related
+    connect(&*linked.owner.callModel, &NewCallModel::newIncomingCall,
+            this, &ConversationModelPimpl::slotIncomingCall);
+    connect(&*linked.owner.contactModel, &ContactModel::incomingCallFromPending,
+            this, &ConversationModelPimpl::slotIncomingCall);
+    connect(&*linked.owner.callModel,
+            &lrc::api::NewCallModel::callStatusChanged,
+            this,
+            &ConversationModelPimpl::slotCallStatusChanged);
+    connect(&*linked.owner.callModel,
+            &lrc::api::NewCallModel::callStarted,
+            this,
+            &ConversationModelPimpl::slotCallStarted);
+    connect(&*linked.owner.callModel,
+            &lrc::api::NewCallModel::callEnded,
+            this,
+            &ConversationModelPimpl::slotCallEnded);
 }
 
 ConversationModelPimpl::~ConversationModelPimpl()
@@ -701,6 +751,17 @@ void
 ConversationModelPimpl::slotCallEnded(const std::string& callId)
 {
     addCallMessage(callId, "🕽 Call ended");
+
+    // reset the callId stored in the conversation
+    auto it = std::find_if(conversations.begin(), conversations.end(),
+    [&](const conversation::Info& conversation) {
+      return conversation.callId == callId;
+    });
+
+    if (it != conversations.end()) {
+        it->callId = "";
+        dirtyConversations = true;
+    }
 }
 
 void
@@ -742,10 +803,10 @@ ConversationModelPimpl::slotNewAccountMessage(std::string& accountId,
 void
 ConversationModelPimpl::slotIncomingCallMessage(const std::string& callId, const std::string& from, const std::string& body)
 {
-    Q_UNUSED(callId);
-    Q_UNUSED(from);
-    Q_UNUSED(body);
-    // at this point we are not yet able to handle incoming call message
+    if (not linked.owner.callModel->hasCall(callId))
+        return;
+
+    addIncomingMessage(from, body);
 }
 
 void
diff --git a/src/newaccountmodel.cpp b/src/newaccountmodel.cpp
index ee9a3388a389e98b11e641de77c589e67805dfb4..cc9da8b7f605cb6d37cd7da410f9fb351b805227 100644
--- a/src/newaccountmodel.cpp
+++ b/src/newaccountmodel.cpp
@@ -169,7 +169,7 @@ NewAccountModelPimpl::addToAccounts(const std::string& accountId)
                                             owner.profileInfo.alias, "",
                                             details["Account.type"].toStdString());
     // Init models for this account
-    owner.callModel = std::make_unique<NewCallModel>(owner);
+    owner.callModel = std::make_unique<NewCallModel>(owner, callbacksHandler);
     owner.contactModel = std::make_unique<ContactModel>(owner, database, callbacksHandler);
     owner.conversationModel = std::make_unique<ConversationModel>(owner, database, callbacksHandler);
     owner.accountModel = &linked;
diff --git a/src/newcallmodel.cpp b/src/newcallmodel.cpp
index 4e29bcd2349f8120b512ba9e36a386a69d15c48c..5fd5cb7d2f210e7b7790154fd7d3e667b705e38b 100644
--- a/src/newcallmodel.cpp
+++ b/src/newcallmodel.cpp
@@ -16,117 +16,398 @@
  *   You should have received a copy of the GNU General Public License      *
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
  ***************************************************************************/
+
 #include "api/newcallmodel.h"
 
-// LRC
+// std
+#include <chrono>
+
+// Lrc
+#include "callbackshandler.h"
+#include "api/conversationmodel.h"
+#include "api/contact.h"
+#include "api/contactmodel.h"
 #include "api/newaccountmodel.h"
-#include "api/call.h"
+#include "dbus/callmanager.h"
+#include "private/videorenderermanager.h"
+#include "video/renderer.h"
+
+// Ring daemon
+#include <media_const.h>
+
+// Qt
+#include <QObject>
+#include <QString>
 
 namespace lrc
 {
 
 using namespace api;
 
-class NewCallModelPimpl
+class NewCallModelPimpl: public QObject
 {
 public:
-    NewCallModelPimpl(NewCallModel& linked);
+    NewCallModelPimpl(const NewCallModel& linked, const CallbacksHandler& callbacksHandler);
     ~NewCallModelPimpl();
 
-    void sendMessage(const std::string& callId, const std::string& body) const;
-
-    const NewCallModel& linked;
     NewCallModel::CallInfoMap calls;
+    const CallbacksHandler& callbacksHandler;
+    const NewCallModel& linked;
+
+    /**
+     * key = peer's uri
+     * vector = chunks
+     * @note chunks are counted from 1 to number of parts. We use 0 to store the actual number of parts stored
+     */
+    std::map<std::string, std::vector<std::string>> vcardsChunks;
+
+public Q_SLOTS:
+    /**
+     * Listen from CallbacksHandler when a call is incoming
+     * @param accountId account which receives the call
+     * @param callId
+     * @param fromId peer uri
+     */
+    void slotIncomingCall(const std::string& accountId, const std::string& callId, const std::string& fromId);
+    /**
+     * Listen from CallbacksHandler when a call got a new state
+     * @param callId
+     * @param state the new state
+     * @param code unused
+     */
+    void slotCallStateChanged(const std::string& callId, const std::string &state, int code);
+    /**
+     * Listen from VideoRendererManager when a Renderer starts
+     * @param callId
+     * @param renderer
+     */
+    void slotRemotePreviewStarted(const std::string& callId, Video::Renderer* renderer);
+    /**
+     * Listen from CallbacksHandler when a VCard chunk is incoming
+     * @param callId
+     * @param from
+     * @param part
+     * @param numberOfParts
+     * @param payload
+     */
+    void slotincomingVCardChunk(const std::string& callId, const std::string& from, int part, int numberOfParts, const std::string& payload);
 };
 
-NewCallModel::NewCallModel(const account::Info& owner)
-: QObject()
-, owner(owner)
-, pimpl_(std::make_unique<NewCallModelPimpl>(*this))
+NewCallModel::NewCallModel(const account::Info& owner, const CallbacksHandler& callbacksHandler)
+: owner(owner)
+, pimpl_(std::make_unique<NewCallModelPimpl>(*this, callbacksHandler))
 {
 
 }
 
 NewCallModel::~NewCallModel()
 {
+}
 
+const call::Info&
+NewCallModel::getCallFromURI(const std::string& uri) const
+{
+    for (const auto& call: pimpl_->calls) {
+        if (call.second->peer == uri) {
+            return *call.second;
+        }
+    }
+    throw std::out_of_range("No call at URI " + uri);
 }
 
 const call::Info&
-NewCallModel::createCall(const std::string& contactUri)
+NewCallModel::getCall(const std::string& uid) const
+{
+    return *pimpl_->calls.at(uid);
+}
+
+std::string
+NewCallModel::createCall(const std::string& url)
 {
+    // do not use auto here (QDBusPendingReply<QString>)
+    QString callId = CallManager::instance().placeCall(owner.id.c_str(), url.c_str());
+
+    if (callId.isEmpty())
+        qDebug() << "no call placed between (account :" << owner.id.c_str() << ", contact :" << url.c_str() << ")";
+
+    auto callInfo = std::make_shared<call::Info>();
+    callInfo->id = callId.toStdString();
+    callInfo->peer = url;
+    callInfo->status =  call::Status::SEARCHING;
+    pimpl_->calls.emplace(callId.toStdString(), std::move(callInfo));
 
+    return callId.toStdString();
 }
 
-const call::Info&
-NewCallModel::getCallFromURI(const std::string& uri) const
+void
+NewCallModel::accept(const std::string& callId) const
 {
-    return {};
+    CallManager::instance().accept(callId.c_str());
 }
 
 void
 NewCallModel::hangUp(const std::string& callId) const
 {
+    CallManager::instance().hangUp(callId.c_str());
+}
 
+void
+NewCallModel::toggleAudioRecord(const std::string& callId) const
+{
+    CallManager::instance().toggleRecording(callId.c_str());
+}
+
+void
+NewCallModel::playDTMF(const std::string& callId, const std::string& value) const
+{
+    auto call = pimpl_->calls.find(callId);
+    if (call == pimpl_->calls.end()) return;
+    if (pimpl_->calls[callId]->status != call::Status::IN_PROGRESS) return;
+    CallManager::instance().playDTMF(value.c_str());
 }
 
 void
 NewCallModel::togglePause(const std::string& callId) const
 {
+    auto call = pimpl_->calls.find(callId);
+    if (call == pimpl_->calls.end()) return;
+    switch(pimpl_->calls[callId]->status)
+    {
+    case call::Status::PAUSED:
+        CallManager::instance().unhold(callId.c_str());
+        break;
+    case call::Status::IN_PROGRESS:
+        CallManager::instance().hold(callId.c_str());
+        break;
+    case call::Status::INVALID:
+    case call::Status::OUTGOING_REQUESTED:
+    case call::Status::INCOMING_RINGING:
+    case call::Status::OUTGOING_RINGING:
+    case call::Status::CONNECTING:
+    case call::Status::SEARCHING:
+    case call::Status::PEER_PAUSED:
+    case call::Status::INACTIVE:
+    case call::Status::ENDED:
+    case call::Status::TERMINATING:
+    case call::Status::CONNECTED:
+    case call::Status::AUTO_ANSWERING:
+        break;
+    }
+}
 
+void
+NewCallModel::toggleMedia(const std::string& callId, const NewCallModel::Media media, bool flag) const
+{
+    switch(media)
+    {
+    case NewCallModel::Media::AUDIO:
+        CallManager::instance().muteLocalMedia(callId.c_str(),
+                                               DRing::Media::Details::MEDIA_TYPE_AUDIO,
+                                               flag);
+        break;
+
+    case NewCallModel::Media::VIDEO:
+        CallManager::instance().muteLocalMedia(callId.c_str(),
+                                               DRing::Media::Details::MEDIA_TYPE_VIDEO,
+                                               flag);
+        break;
+
+    case NewCallModel::Media::NONE:
+    default:
+        break;
+    }
 }
 
 void
-NewCallModel::toggleMedia(const std::string& callId, const Media media) const
+NewCallModel::setQuality(const std::string& callId, const double quality) const
 {
+    qDebug() << "setQuality, isn't yet implemented";
+}
 
+void
+NewCallModel::transfer(const std::string& callId, const std::string& to) const
+{
+    qDebug() << "transfer, isn't yet implemented";
 }
 
 void
-NewCallModel::toggleRecoringdAudio(const std::string& callId) const
+NewCallModel::addParticipant(const std::string& callId, const std::string& participant) const
 {
 
 }
 
 void
-NewCallModel::setQuality(const std::string& callId, const double quality) const
+NewCallModel::removeParticipant(const std::string& callId, const std::string& participant) const
 {
 
 }
 
-void
-NewCallModel::transfer(const std::string& callId, const std::string& to) const
+Video::Renderer*
+NewCallModel::getRenderer(const std::string& callId) const
 {
+   #ifdef ENABLE_VIDEO
+   return VideoRendererManager::instance().getRenderer(callId);
+   #else
+   return nullptr;
+   #endif
+}
 
+std::string
+NewCallModel::getFormattedCallDuration(const std::string& callId) const
+{
+    if (pimpl_->calls.find(callId) == pimpl_->calls.end()) return "00:00";
+    auto& startTime = pimpl_->calls[callId]->startTime;
+    if (startTime.time_since_epoch().count() == 0) return "00:00";
+    auto now = std::chrono::steady_clock::now();
+    auto d = std::chrono::duration_cast<std::chrono::seconds>(
+             now.time_since_epoch() - startTime.time_since_epoch()).count();
+
+    std::string formattedString;
+    auto minutes = d / 60;
+    auto seconds = d % 60;
+    if (minutes > 0) {
+        formattedString += std::to_string(minutes) + ":";
+        if (formattedString.length() == 2) {
+            formattedString = "0" + formattedString;
+        }
+    } else {
+        formattedString += "00:";
+    }
+    if (seconds < 10) formattedString += "0";
+    formattedString += std::to_string(seconds);
+    return formattedString;
 }
 
-void
-NewCallModel::addParticipant(const std::string& callId, const std::string& participant)
+
+NewCallModelPimpl::NewCallModelPimpl(const NewCallModel& linked, const CallbacksHandler& callbacksHandler)
+: linked(linked)
+, callbacksHandler(callbacksHandler)
+{
+    // TODO init call list and conferences if client crash but not the daemon in call.
+    connect(&callbacksHandler, &CallbacksHandler::incomingCall, this, &NewCallModelPimpl::slotIncomingCall);
+    connect(&callbacksHandler, &CallbacksHandler::callStateChanged, this, &NewCallModelPimpl::slotCallStateChanged);
+    connect(&VideoRendererManager::instance(), &VideoRendererManager::remotePreviewStarted, this, &NewCallModelPimpl::slotRemotePreviewStarted);
+    connect(&callbacksHandler, &CallbacksHandler::incomingVCardChunk, this, &NewCallModelPimpl::slotincomingVCardChunk);
+}
+
+NewCallModelPimpl::~NewCallModelPimpl()
 {
 
 }
 
 void
-NewCallModel::removeParticipant(const std::string& callId, const std::string& participant)
+NewCallModel::sendSipMessage(const std::string& callId, const std::string& body) const
 {
+    QMap<QString, QString> payloads;
+    payloads["text/plain"] = body.c_str();
 
+    CallManager::instance().sendTextMessage(callId.c_str(), payloads, true /* not used */);
 }
 
-NewCallModelPimpl::NewCallModelPimpl(NewCallModel& linked)
-: linked(linked)
+void
+NewCallModelPimpl::slotIncomingCall(const std::string& accountId, const std::string& callId, const std::string& fromId)
 {
+    if (linked.owner.id != accountId) return;
+
+    qDebug() << "NewCallModelPimpl::slotIncomingCall";
+
+    auto callInfo = std::make_shared<call::Info>();
+    callInfo->id = callId;
+    callInfo->peer = fromId;
+    callInfo->status =  call::Status::INCOMING_RINGING;
+    calls.emplace(callId, std::move(callInfo));
 
+    emit linked.newIncomingCall(fromId, callId);
 }
 
-NewCallModelPimpl::~NewCallModelPimpl()
+void
+NewCallModelPimpl::slotCallStateChanged(const std::string& callId, const std::string& state, int code)
 {
+    Q_UNUSED(code)
+    if (calls.find(callId) != calls.end()) {
+        if (state == "CONNECTING") {
+            calls[callId]->status = call::Status::CONNECTING;
+        } else if (state == "RINGING") {
+            calls[callId]->status = call::Status::OUTGOING_RINGING;
+        } else if (state == "HUNGUP") {
+            calls[callId]->status = call::Status::TERMINATING;
+        } else if (state == "FAILURE" || state == "OVER") {
+            if (calls[callId]->startTime.time_since_epoch().count() != 0) {
+                emit linked.callEnded(callId);
+            }
+            calls[callId]->status = call::Status::ENDED;
+        } else if (state == "INACTIVE") {
+            calls[callId]->status = call::Status::INACTIVE;
+        } else if (state == "CURRENT") {
+            if (calls[callId]->startTime.time_since_epoch().count() == 0) {
+                calls[callId]->startTime = std::chrono::steady_clock::now();
+                emit linked.callStarted(callId);
+            }
+            calls[callId]->status = call::Status::IN_PROGRESS;
+        } else if (state == "HOLD") {
+            calls[callId]->status = call::Status::PAUSED;
+        }
+        qDebug() << "slotCallStateChanged, call:" << callId.c_str() << " - state: " << state.c_str();
+        emit linked.callStatusChanged(callId);
+    }
+}
 
+void
+NewCallModelPimpl::slotRemotePreviewStarted(const std::string& callId, Video::Renderer* renderer)
+{
+    emit linked.remotePreviewStarted(callId, renderer);
 }
 
 void
-NewCallModelPimpl::sendMessage(const std::string& callId, const std::string& body) const
+NewCallModelPimpl::slotincomingVCardChunk(const std::string& callId,
+                                          const std::string& from,
+                                          int part,
+                                          int numberOfParts,
+                                          const std::string& payload)
 {
+    auto it = calls.find(callId);
+
+    if (it != calls.end()) {
+        auto it_2 = vcardsChunks.find(from);
+        if (it_2 != vcardsChunks.end()) {
+            vcardsChunks[from][part-1] = payload;
+
+            if ( not std::any_of(vcardsChunks[from].begin(), vcardsChunks[from].end(),
+                [](const auto& s) { return s.empty(); }) ) {
+
+                profile::Info profileInfo;
+                profileInfo.uri = from;
+                profileInfo.type = profile::Type::RING;
 
+                std::string vcardPhoto;
+
+                for (auto& chunk : vcardsChunks[from])
+                    vcardPhoto += chunk;
+
+                for (auto& e : QString(vcardPhoto.c_str()).split( "\n" ))
+                    if (e.contains("PHOTO"))
+                        profileInfo.avatar = e.split( ":" )[1].toStdString();
+                    else if (e.contains("FN"))
+                        profileInfo.alias = e.split( ":" )[1].toStdString();
+
+                contact::Info contactInfo;
+                contactInfo.profileInfo = profileInfo;
+
+                linked.owner.contactModel->addContact(contactInfo);
+                vcardsChunks.erase(from); // Transfer is finish, we don't want to reuse this entry.
+            }
+        } else {
+            vcardsChunks[from] = std::vector<std::string>(numberOfParts);
+            vcardsChunks[from][part-1] = payload;
+        }
+
+    }
+}
+
+bool
+NewCallModel::hasCall(const std::string& callId)
+{
+    return pimpl_->calls.find(callId) != pimpl_->calls.end();
 }
 
 } // namespace lrc
diff --git a/src/private/videorenderermanager.cpp b/src/private/videorenderermanager.cpp
index 5cc52a62d3901b746416fd5c7a28557aa659598d..a811dd77eec0581fb688dd26071e9f7807c76eb3 100644
--- a/src/private/videorenderermanager.cpp
+++ b/src/private/videorenderermanager.cpp
@@ -113,6 +113,14 @@ Video::Renderer* VideoRendererManager::getRenderer(const Call* call) const
    return d_ptr->m_hRenderers[call->dringId().toLatin1()];
 }
 
+// helper for the new model
+Video::Renderer* VideoRendererManager::getRenderer(const std::string& callId) const
+{
+   return (d_ptr->m_hRenderers.contains(callId.c_str()))
+          ? d_ptr->m_hRenderers[callId.c_str()]
+          : nullptr;
+}
+
 ///Get the video preview Renderer
 Video::Renderer* VideoRendererManager::previewRenderer()
 {
@@ -258,8 +266,10 @@ void VideoRendererManagerPrivate::startedDecoding(const QString& id, const QStri
 
       Call* c = CallModel::instance().getCall(id);
 
-      if (c)
+      if (c) {
+          emit q_ptr->remotePreviewStarted(id.toStdString(), r);
           c->d_ptr->registerRenderer(r);
+      }
       else {
           //We don't have the conference yet
           QObject::connect(&CallModel::instance(), &CallModel::conferenceCreated, [=](Call* conf) {
diff --git a/src/private/videorenderermanager.h b/src/private/videorenderermanager.h
index b16699390bdb8a15b5e23225fa66b323437c4cd5..5605e561604428e55cc7a387a843036bcc00f7e7 100644
--- a/src/private/videorenderermanager.h
+++ b/src/private/videorenderermanager.h
@@ -54,6 +54,7 @@ public:
 
    //Helpers
    Video::Renderer* getRenderer(const Call* call) const;
+   Video::Renderer* getRenderer(const std::string& callId) const;
    void setBufferSize(uint size);
    void switchDevice(const Video::Device* device) const;
 
@@ -75,6 +76,6 @@ Q_SIGNALS:
    void previewStateChanged(bool startStop);
    void previewStarted(Video::Renderer* renderer);
    void previewStopped(Video::Renderer* renderer);
+   void remotePreviewStarted(const std::string& callId, Video::Renderer* renderer);
 
 };
-