diff --git a/src/api/avmodel.h b/src/api/avmodel.h
index 65cf1023e2f23b14b7ec863c0aecd78b4141dfb2..87d957e2f10fd8cdc86da1e026b957b76a85c191 100644
--- a/src/api/avmodel.h
+++ b/src/api/avmodel.h
@@ -251,7 +251,7 @@ public:
      */
     const video::Renderer& getRenderer(const QString& id) const;
     /**
-     * Render a file to the call id specified
+     * @deprecated Render a file to the call id specified
      * @param uri the path of the file
      * @param callId
      * @note callId can be omitted to switch the input of the local recorder
@@ -266,7 +266,7 @@ public:
      */
     void switchInputTo(const QString& id, const QString& callId = {});
     /**
-     * Render the current display to the call id specified
+     * @deprecated Render the current display to the call id specified
      * @param idx of the display
      * @param x top left of the area
      * @param y top up of the area
@@ -276,6 +276,15 @@ public:
      * @note callId can be omitted to switch the input of the local recorder
      */
     void setDisplay(int idx, int x, int y, int w, int h, const QString& callId = {});
+    /**
+     * Get the current display resource string
+     * @param idx of the display
+     * @param x top left of the area
+     * @param y top up of the area
+     * @param w width of the area
+     * @param h height of the area
+     */
+    QString getDisplay(int idx, int x, int y, int w, int h);
     /**
      * Get informations on the rendered device
      * @param call_id linked call to the renderer
diff --git a/src/api/newcallmodel.h b/src/api/newcallmodel.h
index ca8e5479a85a3e95b83789591ea5625c081965e0..47df435a52012ade73ca9508e2d6908f42a15cc9 100644
--- a/src/api/newcallmodel.h
+++ b/src/api/newcallmodel.h
@@ -67,6 +67,7 @@ public:
     const account::Info& owner;
 
     enum class Media { NONE, AUDIO, VIDEO };
+    enum class MediaRequestType { FILESHARING, SCREENSHARING, CAMERA };
 
     NewCallModel(const account::Info& owner,
                  const CallbacksHandler& callbacksHandler,
@@ -85,8 +86,15 @@ public:
      * Request a media change in a ongoing call.
      * @param  callId
      * @param  mediaLabel label of media to be changed
-     */
-    void requestMediaChange(const QString& callId, const QString& mediaLabel);
+     * @param source
+     * @param type
+     * @param mute
+     */
+    void requestMediaChange(const QString& callId,
+                            const QString& mediaLabel,
+                            const QString& source,
+                            MediaRequestType type,
+                            bool mute);
 
     /**
      * Get the call from its call id
diff --git a/src/avmodel.cpp b/src/avmodel.cpp
index 43cb55bdcbe8cc6efb98b6faf7ce38a5815d3e4e..c261a2e1de6fefc6e2c2483e079f6fdace4bc203 100644
--- a/src/avmodel.cpp
+++ b/src/avmodel.cpp
@@ -555,9 +555,20 @@ AVModel::setInputFile(const QString& uri, const QString& callId)
 
 void
 AVModel::setDisplay(int idx, int x, int y, int w, int h, const QString& callId)
+{
+    auto resource = getDisplay(idx, x, y, w, h);
+    if (callId.isEmpty()) {
+        VideoManager::instance().switchInput(resource);
+    } else {
+        CallManager::instance().switchInput(callId, resource);
+    }
+}
+
+QString
+AVModel::getDisplay(int idx, int x, int y, int w, int h)
 {
     QString sep = DRing::Media::VideoProtocolPrefix::SEPARATOR;
-    auto resource = QString("%1%2:%3+%4,%5 %6x%7")
+    return QString("%1%2:%3+%4,%5 %6x%7")
                         .arg(DRing::Media::VideoProtocolPrefix::DISPLAY)
                         .arg(sep)
                         .arg(idx)
@@ -565,11 +576,6 @@ AVModel::setDisplay(int idx, int x, int y, int w, int h, const QString& callId)
                         .arg(y)
                         .arg(w)
                         .arg(h);
-    if (callId.isEmpty()) {
-        VideoManager::instance().switchInput(resource);
-    } else {
-        CallManager::instance().switchInput(callId, resource);
-    }
 }
 
 void
diff --git a/src/newcallmodel.cpp b/src/newcallmodel.cpp
index ad91b6c1f08c3f7959c38bad9313d57bc46602bc..0d26ae6fa71cead8fffaf93d29673f5354dfff21 100644
--- a/src/newcallmodel.cpp
+++ b/src/newcallmodel.cpp
@@ -42,6 +42,7 @@
 // Qt
 #include <QObject>
 #include <QString>
+#include <QUrl>
 
 // std
 #include <chrono>
@@ -357,7 +358,7 @@ NewCallModel::createCall(const QString& uri, bool isAudioOnly, VectorMapStringSt
 }
 
 void
-NewCallModel::requestMediaChange(const QString& callId, const QString& mediaLabel)
+NewCallModel::requestMediaChange(const QString& callId, const QString& mediaLabel, const QString& uri, MediaRequestType type, bool mute)
 {
     // Main audio: audio_0
     // Main video: video_0
@@ -366,57 +367,102 @@ NewCallModel::requestMediaChange(const QString& callId, const QString& mediaLabe
     if (!callInfo)
         return;
 
-    if (callInfo->type == call::Type::CONFERENCE) {
-        if (mediaLabel.contains("audio_0")) {
-            CallManager::instance().muteLocalMedia(callId,
-                                                   DRing::Media::Details::MEDIA_TYPE_AUDIO,
-                                                   !callInfo->audioMuted);
-            callInfo->audioMuted = !callInfo->audioMuted;
-        } else if (mediaLabel.contains("video_0")) {
-            CallManager::instance().muteLocalMedia(callId,
-                                                   DRing::Media::Details::MEDIA_TYPE_VIDEO,
-                                                   !callInfo->videoMuted);
-            callInfo->videoMuted = !callInfo->videoMuted;
+    QString sep = DRing::Media::VideoProtocolPrefix::SEPARATOR;
+    QString resource = "";
+    int found = 0;
+    QString srctype = MediaAttributeValue::SRC_TYPE_CAPTURE_DEVICE;
+
+    switch (type) {
+    case MediaRequestType::FILESHARING: {
+        // File sharing
+        resource = !uri.isEmpty() ? QString("%1%2%3")
+                                        .arg(DRing::Media::VideoProtocolPrefix::FILE)
+                                        .arg(sep)
+                                        .arg(QUrl(uri).toLocalFile())
+                                  : DRing::Media::VideoProtocolPrefix::NONE;
+        if (callInfo->type == call::Type::CONFERENCE) {
+            CallManager::instance().switchInput(callId, resource);
+            return;
         }
-        if (callInfo->status == call::Status::IN_PROGRESS)
-            emit callInfosChanged(owner.id, callId);
+        if (!resource.isEmpty())
+            srctype = MediaAttributeValue::SRC_TYPE_FILE;
+
+        break;
+    }
+    case MediaRequestType::SCREENSHARING: {
+        // Screen/window sharing
+        resource = uri;
+        if (callInfo->type == call::Type::CONFERENCE) {
+            CallManager::instance().switchInput(callId, resource);
+            return;
+        }
+        srctype = MediaAttributeValue::SRC_TYPE_DISPLAY;
+        break;
+    }
+    case MediaRequestType::CAMERA: {
+        // Camera device
+        resource = !uri.isEmpty() ? QString("%1%2%3")
+                                        .arg(DRing::Media::VideoProtocolPrefix::CAMERA)
+                                        .arg(sep)
+                                        .arg(uri)
+                                  : DRing::Media::VideoProtocolPrefix::NONE;
+
+        if (callInfo->type == call::Type::CONFERENCE) {
+            if (mediaLabel.contains("audio_0")) {
+                CallManager::instance().muteLocalMedia(callId,
+                                                       DRing::Media::Details::MEDIA_TYPE_AUDIO,
+                                                       !callInfo->audioMuted && mute);
+            } else if (mediaLabel.contains("video_0")) {
+                CallManager::instance().muteLocalMedia(callId,
+                                                       DRing::Media::Details::MEDIA_TYPE_VIDEO,
+                                                       !callInfo->videoMuted && mute);
+            }
+            return;
+        }
+
+        srctype = MediaAttributeValue::SRC_TYPE_CAPTURE_DEVICE;
+        break;
+    }
+    default:
         return;
     }
 
     auto proposedList = callInfo->mediaList;
-
-    int found = 0;
     for (auto& item : proposedList) {
         if (item[MediaAttributeKey::LABEL] == mediaLabel) {
+            mute = resource.isEmpty() ? item[MediaAttributeKey::MUTED] == "false" : mute;
             item[MediaAttributeKey::ENABLED] = "true";
-            item[MediaAttributeKey::MUTED] = item[MediaAttributeKey::MUTED] == "true" ? "false"
-                                                                                      : "true";
+            item[MediaAttributeKey::MUTED] = mute ? "true" : "false";
+            item[MediaAttributeKey::SOURCE_TYPE] = srctype;
+            item[MediaAttributeKey::SOURCE] = resource.isEmpty() ? item[MediaAttributeKey::SOURCE] : resource;
+
             break;
         }
         found++;
     }
+
     if (found == proposedList.size() && mediaLabel == "video_0") {
+        mute &= !resource.isEmpty();
         MapStringString mediaAttribute = {{MediaAttributeKey::MEDIA_TYPE,
                                            MediaAttributeValue::VIDEO},
                                           {MediaAttributeKey::ENABLED, "true"},
-                                          {MediaAttributeKey::MUTED, "false"},
-                                          {MediaAttributeKey::SOURCE, ""},
-                                          {MediaAttributeKey::LABEL, "video_0"}};
+                                          {MediaAttributeKey::MUTED,
+                                           mute ? "true" : "false"},
+                                          {MediaAttributeKey::SOURCE_TYPE, srctype},
+                                          {MediaAttributeKey::SOURCE, resource},
+                                          {MediaAttributeKey::LABEL, mediaLabel}};
         proposedList.push_back(mediaAttribute);
-        // We should prepare it here for adding file and screen sharing
-        // for now it supports only adding main video to an audio only call
     }
     CallManager::instance().requestMediaChange(callId, proposedList);
     // If media existed and its mute state was changed here, then we should
     // update the mediaList because we will not receive signal
     // mediaNegotiationStatus
     if (found < callInfo->mediaList.size()) {
-        callInfo->mediaList[found][MediaAttributeKey::MUTED]
-            = callInfo->mediaList[found][MediaAttributeKey::MUTED] == "true" ? "false" : "true";
+        callInfo->mediaList = proposedList;
         if (mediaLabel.contains("audio_0")) {
-            callInfo->audioMuted = !callInfo->audioMuted;
+            callInfo->audioMuted = mute;
         } else if (mediaLabel.contains("video_0")) {
-            callInfo->videoMuted = !callInfo->videoMuted;
+            callInfo->videoMuted = mute;
         }
         if (callInfo->status == call::Status::IN_PROGRESS)
             emit callInfosChanged(owner.id, callId);
@@ -516,7 +562,7 @@ NewCallModel::toggleMedia(const QString& callId, const NewCallModel::Media media
     if (!hasCall(callId))
         return;
     auto mediaLabel = media == NewCallModel::Media::VIDEO ? "video_0" : "audio_0";
-    requestMediaChange(callId, mediaLabel);
+    requestMediaChange(callId, mediaLabel, "", MediaRequestType::CAMERA, true);
 }
 
 void