From bc95054184b76fc328f73647f58e6cd83bc7dfd0 Mon Sep 17 00:00:00 2001
From: Julien Grossholtz <julien.grossholtz@savoirfairelinux.com>
Date: Wed, 21 Oct 2015 17:06:24 -0400
Subject: [PATCH] media: create and update video media from call details

We must make sure LRC knows what is the source video for
each call.

Dbus call "Call details" now contains information about the source
used for outgoing video data. This patch takes this information
to fill the Sourcemodel. The sourceModel itself is put into
a Media::Video related with the call.

Change-Id: I0887a8b9076e23fe33a698e4f3b7d1898b3b3608
Tuleap: #100
---
 src/call.cpp                     | 26 +++++++++++
 src/media/video.cpp              | 14 +++++-
 src/media/video.h                |  6 +++
 src/private/call_p.h             |  1 +
 src/video/configurationproxy.cpp | 74 +++++++++++++++++++++-----------
 src/video/sourcemodel.cpp        | 54 +++++++++++++++--------
 src/video/sourcemodel.h          |  9 ++--
 7 files changed, 137 insertions(+), 47 deletions(-)

diff --git a/src/call.cpp b/src/call.cpp
index 176532f1..d2e25418 100644
--- a/src/call.cpp
+++ b/src/call.cpp
@@ -55,6 +55,7 @@
 #include "phonedirectorymodel.h"
 #include "contactmethod.h"
 #include "video/renderer.h"
+#include "video/sourcemodel.h"
 #include "tlsmethodmodel.h"
 #include "audio/settings.h"
 #include "personmodel.h"
@@ -388,6 +389,28 @@ void CallPrivate::deleteCall(Call* call)
     delete call;
 }
 
+void CallPrivate::updateOutgoingMedia(const MapStringString& details)
+{
+   auto list = q_ptr->media(Media::Media::Type::VIDEO, Media::Media::Direction::OUT);
+   QString video_source  = details[ DRing::Call::Details::VIDEO_SOURCE];
+
+   if (video_source.length() <= 0 && list.isEmpty()) {
+       // Means there is no video, and there never was. Nothing to do.
+       return;
+   }
+
+   if (list.isEmpty()) {
+       // Update data
+       static const Media::Media::Direction direction = Media::Media::Direction::OUT;
+       mediaFactory<Media::Video>(direction);
+   }
+
+   list = q_ptr->media(Media::Media::Type::VIDEO, Media::Media::Direction::OUT);
+   Media::Video* media_video = static_cast<Media::Video*>(list[0]);
+   media_video->sourceModel()->setUsedIndex(video_source);
+   return;
+}
+
 MapStringString CallPrivate::getCallDetailsCommon(const QString& callId)
 {
    CallManagerInterface& callManager = CallManager::instance();
@@ -437,6 +460,7 @@ Call* CallPrivate::buildCall(const QString& callId, Call::Direction callDirectio
 
     auto call = std::unique_ptr<Call, decltype(deleteCall)&>( new Call(startState, peerName, nb, acc),
                                                              deleteCall );
+    call->d_ptr->updateOutgoingMedia(details);
 
     call->d_ptr->m_DringId      = callId;
     call->d_ptr->m_Direction    = callDirection;
@@ -1251,6 +1275,8 @@ Call::State CallPrivate::stateChanged(const QString& newStateName)
       }
 
       MapStringString details = getCallDetailsCommon(m_DringId);
+      updateOutgoingMedia(details);
+
       if (!details[DRing::Call::Details::DISPLAY_NAME].isEmpty()
           and ( details[DRing::Call::Details::DISPLAY_NAME] != m_PeerName) )
          m_PeerName = details[DRing::Call::Details::DISPLAY_NAME];
diff --git a/src/media/video.cpp b/src/media/video.cpp
index 198b5d71..cf254d57 100644
--- a/src/media/video.cpp
+++ b/src/media/video.cpp
@@ -19,6 +19,7 @@
 
 //Dring
 #include <media_const.h>
+#include <video/sourcemodel.h>
 #include "dbus/callmanager.h"
 
 //Ring
@@ -26,6 +27,8 @@
 
 class MediaVideoPrivate
 {
+public:
+    Video::SourceModel *m_pSourceModel = nullptr;
 };
 
 Media::Video::Video(Call* parent, const Media::Direction direction) : Media::Media(parent, direction), d_ptr(new MediaVideoPrivate())
@@ -50,7 +53,16 @@ bool Media::Video::unmute()
    return callManager.muteLocalMedia(call()->dringId(),DRing::Media::Details::MEDIA_TYPE_VIDEO,false);
 }
 
+Video::SourceModel* Media::Video::sourceModel() const
+{
+    if (!d_ptr->m_pSourceModel) {
+        d_ptr->m_pSourceModel = new ::Video::SourceModel();
+    }
+
+    return d_ptr->m_pSourceModel;
+}
+
 Media::Video::~Video()
 {
    delete d_ptr;
-}
\ No newline at end of file
+}
diff --git a/src/media/video.h b/src/media/video.h
index c71237fc..9073f861 100644
--- a/src/media/video.h
+++ b/src/media/video.h
@@ -20,6 +20,11 @@
 #include <media/media.h>
 #include <typedefs.h>
 
+namespace Video{
+class SourceModel;
+}
+
+
 class MediaVideoPrivate;
 class Call;
 class CallPrivate;
@@ -34,6 +39,7 @@ public:
    virtual Media::Type type() override;
    virtual bool mute() override;
    virtual bool unmute() override;
+   ::Video::SourceModel* sourceModel() const;
 
 private:
    Video(Call* parent, const Media::Direction direction);
diff --git a/src/private/call_p.h b/src/private/call_p.h
index 56e38933..0ba8a0e2 100644
--- a/src/private/call_p.h
+++ b/src/private/call_p.h
@@ -237,6 +237,7 @@ public:
    void peerHoldChanged(bool onPeerHold);
    template<typename T>
    T* mediaFactory(Media::Media::Direction dir);
+   void updateOutgoingMedia(const MapStringString& details);
 
    //Static getters
    static Call::State        startStateFromDaemonCallState ( const QString& daemonCallState, const QString& daemonCallType );
diff --git a/src/video/configurationproxy.cpp b/src/video/configurationproxy.cpp
index f71a4e1d..c6ac3db0 100644
--- a/src/video/configurationproxy.cpp
+++ b/src/video/configurationproxy.cpp
@@ -40,6 +40,8 @@ namespace ConfigurationProxyPrivate {
    static QItemSelectionModel* m_spResolutionSelectionModel= nullptr;
    static QItemSelectionModel* m_spRateSelectionModel      = nullptr;
 
+   static Video::SourceModel*  m_sourceModel = nullptr;
+
    //Helper
    static Video::Device*     currentDevice    ();
    static Video::Channel*    currentChannel   ();
@@ -60,7 +62,7 @@ namespace ConfigurationProxyPrivate {
 QAbstractItemModel& Video::ConfigurationProxy::deviceModel()
 {
    if (!ConfigurationProxyPrivate::m_spDeviceModel) {
-      ConfigurationProxyPrivate::m_spDeviceModel = new QIdentityProxyModel(&Video::SourceModel::instance());
+      ConfigurationProxyPrivate::m_spDeviceModel = new QIdentityProxyModel(ConfigurationProxyPrivate::m_sourceModel);
       ConfigurationProxyPrivate::m_spDeviceModel->setSourceModel(&Video::DeviceModel::instance());
       ConfigurationProxyPrivate::updateDeviceSelection();
    }
@@ -104,7 +106,9 @@ static Video::Resolution* ConfigurationProxyPrivate::currentResolution()
 
 void ConfigurationProxyPrivate::changeDevice()
 {
-   Video::DeviceModel::instance().setActive(Video::ConfigurationProxy::deviceSelectionModel().currentIndex());
+   Video::ConfigurationProxy::deviceSelectionModel();
+
+   Video::DeviceModel::instance().setActive(ConfigurationProxyPrivate::m_spDeviceSelectionModel->currentIndex());
 
    reinterpret_cast<QIdentityProxyModel&>(Video::ConfigurationProxy::channelModel()).setSourceModel(ConfigurationProxyPrivate::currentDevice());
    changeChannel();
@@ -112,8 +116,12 @@ void ConfigurationProxyPrivate::changeDevice()
 
 void ConfigurationProxyPrivate::changeChannel()
 {
-   if (auto dev = ConfigurationProxyPrivate::currentDevice())
-     dev->setActiveChannel(Video::ConfigurationProxy::channelSelectionModel().currentIndex().row());
+   Video::ConfigurationProxy::channelSelectionModel();
+
+   Video::Device* dev = ConfigurationProxyPrivate::currentDevice();
+
+   if (dev)
+      dev->setActiveChannel(ConfigurationProxyPrivate::m_spChannelSelectionModel->currentIndex().row());
 
    reinterpret_cast<QIdentityProxyModel&>(Video::ConfigurationProxy::resolutionModel()).setSourceModel(ConfigurationProxyPrivate::currentChannel());
 
@@ -124,8 +132,12 @@ void ConfigurationProxyPrivate::changeChannel()
 
 void ConfigurationProxyPrivate::changeResolution()
 {
-   if (auto chan = ConfigurationProxyPrivate::currentChannel())
-     chan->setActiveResolution(Video::ConfigurationProxy::resolutionSelectionModel().currentIndex().row());
+   Video::ConfigurationProxy::resolutionSelectionModel();
+
+   Video::Channel* chan = ConfigurationProxyPrivate::currentChannel();
+
+   if (chan)
+      chan->setActiveResolution(ConfigurationProxyPrivate::m_spResolutionSelectionModel->currentIndex().row());
 
    reinterpret_cast<QIdentityProxyModel&>(Video::ConfigurationProxy::rateModel()).setSourceModel(ConfigurationProxyPrivate::currentResolution());
 
@@ -136,8 +148,12 @@ void ConfigurationProxyPrivate::changeResolution()
 
 void ConfigurationProxyPrivate::changeRate()
 {
-   if (auto res = ConfigurationProxyPrivate::currentResolution())
-     res->setActiveRate(Video::ConfigurationProxy::rateSelectionModel().currentIndex().row());
+   Video::ConfigurationProxy::rateSelectionModel();
+
+   Video::Resolution* res = ConfigurationProxyPrivate::currentResolution();
+
+   if (res)
+      res->setActiveRate(ConfigurationProxyPrivate::m_spRateSelectionModel->currentIndex().row());
 
    updateRateSelection();
 }
@@ -153,8 +169,10 @@ void ConfigurationProxyPrivate::updateDeviceSelection()
 
 void ConfigurationProxyPrivate::updateChannelSelection()
 {
-   if (auto dev = ConfigurationProxyPrivate::currentDevice()) {
-      if (auto chan = dev->activeChannel()) {
+   Video::Device* dev = ConfigurationProxyPrivate::currentDevice();
+   if (dev) {
+      Video::Channel* chan = dev->activeChannel();
+      if (chan) {
          const QModelIndex& newIdx = dev->index(chan->relativeIndex(),0);
          if (newIdx.row() != Video::ConfigurationProxy::channelSelectionModel().currentIndex().row())
             Video::ConfigurationProxy::channelSelectionModel().setCurrentIndex(newIdx, QItemSelectionModel::ClearAndSelect );
@@ -164,8 +182,10 @@ void ConfigurationProxyPrivate::updateChannelSelection()
 
 void ConfigurationProxyPrivate::updateResolutionSelection()
 {
-   if (auto chan = ConfigurationProxyPrivate::currentChannel()) {
-      if (auto res = chan->activeResolution()) {
+   Video::Channel* chan = ConfigurationProxyPrivate::currentChannel();
+   if (chan) {
+      Video::Resolution* res = chan->activeResolution();
+      if (res) {
          const QModelIndex& newIdx = chan->index(res->relativeIndex(),0);
          if (newIdx.row() != Video::ConfigurationProxy::resolutionSelectionModel().currentIndex().row())
             Video::ConfigurationProxy::resolutionSelectionModel().setCurrentIndex(newIdx, QItemSelectionModel::ClearAndSelect);
@@ -175,8 +195,10 @@ void ConfigurationProxyPrivate::updateResolutionSelection()
 
 void ConfigurationProxyPrivate::updateRateSelection()
 {
-   if (auto res = ConfigurationProxyPrivate::currentResolution()) {
-      if (auto rate = res->activeRate()) {
+   Video::Resolution* res = ConfigurationProxyPrivate::currentResolution();
+   if (res) {
+      Video::Rate* rate = res->activeRate();
+      if (rate) {
          const QModelIndex& newIdx = res->index(rate->relativeIndex(),0);
          if (newIdx.row() != Video::ConfigurationProxy::rateSelectionModel().currentIndex().row())
             Video::ConfigurationProxy::rateSelectionModel().setCurrentIndex(newIdx, QItemSelectionModel::ClearAndSelect);
@@ -187,9 +209,11 @@ void ConfigurationProxyPrivate::updateRateSelection()
 QAbstractItemModel& Video::ConfigurationProxy::channelModel()
 {
    if (!ConfigurationProxyPrivate::m_spChannelModel) {
-      ConfigurationProxyPrivate::m_spChannelModel = new QIdentityProxyModel(&Video::SourceModel::instance());
-      if (auto dev = ConfigurationProxyPrivate::currentDevice())
+      ConfigurationProxyPrivate::m_spChannelModel = new QIdentityProxyModel(ConfigurationProxyPrivate::m_sourceModel);
+      Video::Device* dev = ConfigurationProxyPrivate::currentDevice();
+      if (dev) {
          ConfigurationProxyPrivate::m_spChannelModel->setSourceModel(dev);
+      }
    }
    return *ConfigurationProxyPrivate::m_spChannelModel;
 }
@@ -197,9 +221,11 @@ QAbstractItemModel& Video::ConfigurationProxy::channelModel()
 QAbstractItemModel& Video::ConfigurationProxy::resolutionModel()
 {
    if (!ConfigurationProxyPrivate::m_spResolutionModel) {
-      ConfigurationProxyPrivate::m_spResolutionModel = new QIdentityProxyModel(&Video::SourceModel::instance());
-      if (auto chan = ConfigurationProxyPrivate::currentChannel())
+      ConfigurationProxyPrivate::m_spResolutionModel = new QIdentityProxyModel(ConfigurationProxyPrivate::m_sourceModel);
+      Video::Channel* chan = ConfigurationProxyPrivate::currentChannel();
+      if (chan) {
          ConfigurationProxyPrivate::m_spResolutionModel->setSourceModel(chan);
+      }
    }
    return *ConfigurationProxyPrivate::m_spResolutionModel;
 }
@@ -207,7 +233,7 @@ QAbstractItemModel& Video::ConfigurationProxy::resolutionModel()
 QAbstractItemModel& Video::ConfigurationProxy::rateModel()
 {
    if (!ConfigurationProxyPrivate::m_spRateModel) {
-      ConfigurationProxyPrivate::m_spRateModel = new QIdentityProxyModel(&Video::SourceModel::instance());
+      ConfigurationProxyPrivate::m_spRateModel = new QIdentityProxyModel(ConfigurationProxyPrivate::m_sourceModel);
       ConfigurationProxyPrivate::m_spRateModel->setSourceModel(ConfigurationProxyPrivate::currentResolution());
    }
    return *ConfigurationProxyPrivate::m_spRateModel;
@@ -216,13 +242,13 @@ QAbstractItemModel& Video::ConfigurationProxy::rateModel()
 QItemSelectionModel& Video::ConfigurationProxy::deviceSelectionModel()
 {
    if (!ConfigurationProxyPrivate::m_spDeviceSelectionModel) {
-      ConfigurationProxyPrivate::m_spDeviceSelectionModel = new QItemSelectionModel(&deviceModel());
+      ConfigurationProxyPrivate::m_spDeviceSelectionModel = new QItemSelectionModel(ConfigurationProxyPrivate::m_spDeviceModel);
 
       ConfigurationProxyPrivate::updateDeviceSelection();
 
       //Can happen if a device is removed
       QObject::connect(&Video::DeviceModel::instance(), &Video::DeviceModel::currentIndexChanged,[](int idx) {
-         ConfigurationProxyPrivate::m_spDeviceSelectionModel->setCurrentIndex(deviceModel().index(idx,0), QItemSelectionModel::ClearAndSelect );
+         ConfigurationProxyPrivate::m_spDeviceSelectionModel->setCurrentIndex(ConfigurationProxyPrivate::m_spDeviceModel->index(idx,0), QItemSelectionModel::ClearAndSelect );
       });
 
       QObject::connect(ConfigurationProxyPrivate::m_spDeviceSelectionModel,&QItemSelectionModel::currentChanged, &ConfigurationProxyPrivate::changeDevice);
@@ -233,7 +259,7 @@ QItemSelectionModel& Video::ConfigurationProxy::deviceSelectionModel()
 QItemSelectionModel& Video::ConfigurationProxy::channelSelectionModel()
 {
    if (!ConfigurationProxyPrivate::m_spChannelSelectionModel) {
-      ConfigurationProxyPrivate::m_spChannelSelectionModel = new QItemSelectionModel(&channelModel());
+      ConfigurationProxyPrivate::m_spChannelSelectionModel = new QItemSelectionModel(ConfigurationProxyPrivate::m_spChannelModel);
 
       ConfigurationProxyPrivate::updateChannelSelection();
 
@@ -245,7 +271,7 @@ QItemSelectionModel& Video::ConfigurationProxy::channelSelectionModel()
 QItemSelectionModel& Video::ConfigurationProxy::resolutionSelectionModel()
 {
    if (!ConfigurationProxyPrivate::m_spResolutionSelectionModel) {
-      ConfigurationProxyPrivate::m_spResolutionSelectionModel = new QItemSelectionModel(&resolutionModel());
+      ConfigurationProxyPrivate::m_spResolutionSelectionModel = new QItemSelectionModel(ConfigurationProxyPrivate::m_spResolutionModel);
 
       ConfigurationProxyPrivate::updateResolutionSelection();
 
@@ -257,7 +283,7 @@ QItemSelectionModel& Video::ConfigurationProxy::resolutionSelectionModel()
 QItemSelectionModel& Video::ConfigurationProxy::rateSelectionModel()
 {
    if (!ConfigurationProxyPrivate::m_spRateSelectionModel) {
-      ConfigurationProxyPrivate::m_spRateSelectionModel = new QItemSelectionModel(&rateModel());
+      ConfigurationProxyPrivate::m_spRateSelectionModel = new QItemSelectionModel(ConfigurationProxyPrivate::m_spRateModel);
 
       ConfigurationProxyPrivate::updateRateSelection();
 
diff --git a/src/video/sourcemodel.cpp b/src/video/sourcemodel.cpp
index de57de75..d6a36a0e 100644
--- a/src/video/sourcemodel.cpp
+++ b/src/video/sourcemodel.cpp
@@ -20,6 +20,7 @@
 #include <QtCore/QCoreApplication>
 #include "../dbus/videomanager.h"
 #include "devicemodel.h"
+#include "callmodel.h"
 
 namespace Video {
 class SourceModelPrivate
@@ -50,10 +51,9 @@ public:
 
 Video::SourceModelPrivate::SourceModelPrivate() : m_CurrentSelection(-1)
 {
-
 }
 
-Video::SourceModel::SourceModel() : QAbstractListModel(QCoreApplication::instance()),
+Video::SourceModel::SourceModel(QObject* parent) : QAbstractListModel(parent),
 d_ptr(new Video::SourceModelPrivate())
 {
    d_ptr->m_Display.rect = QRect(0,0,0,0);
@@ -64,12 +64,6 @@ Video::SourceModel::~SourceModel()
    delete d_ptr;
 }
 
-Video::SourceModel& Video::SourceModel::instance()
-{
-   static auto instance = new Video::SourceModel;
-   return *instance;
-}
-
 QHash<int,QByteArray> Video::SourceModel::roleNames() const
 {
    static QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
@@ -143,8 +137,7 @@ void Video::SourceModel::switchTo(const QModelIndex& idx)
 ///This model is designed for "live" switching rather than configuration
 void Video::SourceModel::switchTo(const int idx)
 {
-   auto newIdx = idx > -1 ? idx : ExtendedDeviceList::NONE;
-   switch (newIdx) {
+   switch (idx) {
       case ExtendedDeviceList::NONE:
          VideoManager::instance().switchInput(Video::SourceModelPrivate::ProtocolPrefix::NONE);
          break;
@@ -164,11 +157,41 @@ void Video::SourceModel::switchTo(const int idx)
       default:
          VideoManager::instance().switchInput(Video::SourceModelPrivate::ProtocolPrefix::CAMERA +
             Video::DeviceModel::instance().index(idx-ExtendedDeviceList::COUNT__,0).data(Qt::DisplayRole).toString());
-         Video::DeviceModel::instance().setActive(idx-ExtendedDeviceList::COUNT__);
-         newIdx = -1;
          break;
    };
-   d_ptr->m_CurrentSelection = newIdx;
+}
+
+///Set the index of the currently used source
+void Video::SourceModel::setUsedIndex(QString &deviceStr)
+{
+    int idx = 0;
+    //find out index here
+    if (deviceStr.length() <= 0) {
+        idx = ExtendedDeviceList::NONE;
+    }
+    else if (deviceStr.indexOf(Video::SourceModelPrivate::ProtocolPrefix::DISPLAY) == 0) {
+        // Look for the display string into the incomming device string
+        idx = ExtendedDeviceList::SCREEN;
+    }
+    else if (deviceStr.indexOf(Video::SourceModelPrivate::ProtocolPrefix::FILE) == 0) {
+        idx = ExtendedDeviceList::FILE;
+    }
+    else if (deviceStr.indexOf(Video::SourceModelPrivate::ProtocolPrefix::CAMERA) == 0) {
+        Video::Device* dev = Video::DeviceModel::instance().getDevice(deviceStr.replace(Video::SourceModelPrivate::ProtocolPrefix::CAMERA,""));
+        if (dev == nullptr) {
+            // Device not found we dont know what camera is used
+            idx = ExtendedDeviceList::NONE;
+            return;
+        }
+
+        Video::DeviceModel::instance().setActive(dev);
+        idx = ExtendedDeviceList::COUNT__ + Video::DeviceModel::instance().activeIndex();
+    }
+    else {
+        idx = ExtendedDeviceList::NONE;
+    }
+
+    d_ptr->m_CurrentSelection = idx;
 }
 
 void Video::SourceModel::switchTo(Video::Device* device)
@@ -191,10 +214,7 @@ Video::Device* Video::SourceModel::deviceAt(const QModelIndex& idx) const
 
 int Video::SourceModel::activeIndex() const
 {
-   if (d_ptr->m_CurrentSelection == -1) {
-      return ExtendedDeviceList::COUNT__ + Video::DeviceModel::instance().activeIndex();
-   }
-   return d_ptr->m_CurrentSelection;
+    return d_ptr->m_CurrentSelection;
 }
 
 void Video::SourceModel::setFile(const QUrl& url)
diff --git a/src/video/sourcemodel.h b/src/video/sourcemodel.h
index 644be2d6..13c69232 100644
--- a/src/video/sourcemodel.h
+++ b/src/video/sourcemodel.h
@@ -32,6 +32,9 @@ class SourceModelPrivate;
 class LIB_EXPORT SourceModel : public QAbstractListModel {
    Q_OBJECT
 public:
+   explicit SourceModel(QObject* parent = nullptr);
+   virtual ~SourceModel();
+
    enum ExtendedDeviceList {
       NONE   ,
       SCREEN ,
@@ -49,13 +52,9 @@ public:
    int activeIndex() const;
 
    int getDeviceIndex(Video::Device* device);
+   void setUsedIndex(QString& deviceStr);
 
-   //Singleton
-   static Video::SourceModel& instance();
 private:
-   explicit SourceModel();
-   virtual ~SourceModel();
-
    Video::SourceModelPrivate* d_ptr;
 
 public Q_SLOTS:
-- 
GitLab