From 143c62f5acfe17c2b7fb2d71d9708cb9db4a3e5c Mon Sep 17 00:00:00 2001
From: agsantos <aline.gondimsantos@savoirfairelinux.com>
Date: Fri, 10 Jul 2020 11:51:44 -0400
Subject: [PATCH] plugin: toggle callmediahandler with callID

Change-Id: I4620a3a2704ea9bca661f00e0f7e6da55f2cb909
---
 src/dring/plugin_manager_interface.h |  17 +++--
 src/plugin/callservicesmanager.h     | 102 ++++++++++++++++++++-------
 src/plugin/jamipluginmanager.cpp     |   6 +-
 src/sip/sipcall.cpp                  |   6 ++
 4 files changed, 97 insertions(+), 34 deletions(-)

diff --git a/src/dring/plugin_manager_interface.h b/src/dring/plugin_manager_interface.h
index 243127c32b..e99a5459f1 100644
--- a/src/dring/plugin_manager_interface.h
+++ b/src/dring/plugin_manager_interface.h
@@ -36,13 +36,12 @@ namespace DRing {
 DRING_PUBLIC bool loadPlugin(const std::string& path);
 DRING_PUBLIC bool unloadPlugin(const std::string& path);
 DRING_PUBLIC void togglePlugin(const std::string& path, bool toggle);
-DRING_PUBLIC std::map<std::string, std::string> getPluginDetails(const std::string& path);
-DRING_PUBLIC std::vector<std::map<std::string, std::string>> getPluginPreferences(
-    const std::string& path);
+DRING_PUBLIC std::map<std::string,std::string> getPluginDetails(const std::string& path);
+DRING_PUBLIC std::vector<std::map<std::string,std::string>> getPluginPreferences(const std::string& path);
 DRING_PUBLIC bool setPluginPreference(const std::string& path,
-                                      const std::string& key,
-                                      const std::string& value);
-DRING_PUBLIC std::map<std::string, std::string> getPluginPreferencesValues(const std::string& path);
+                                        const std::string& key,
+                                        const std::string& value);
+DRING_PUBLIC std::map<std::string,std::string> getPluginPreferencesValues(const std::string& path);
 DRING_PUBLIC bool resetPluginPreferencesValues(const std::string& path);
 DRING_PUBLIC std::vector<std::string> listAvailablePlugins();
 DRING_PUBLIC std::vector<std::string> listLoadedPlugins();
@@ -50,8 +49,8 @@ DRING_PUBLIC int installPlugin(const std::string& jplPath, bool force);
 DRING_PUBLIC int uninstallPlugin(const std::string& pluginRootPath);
 DRING_PUBLIC std::vector<std::string> listCallMediaHandlers();
 DRING_PUBLIC void toggleCallMediaHandler(const std::string& id, bool toggle);
-DRING_PUBLIC std::map<std::string, std::string> getCallMediaHandlerDetails(const std::string& id);
+DRING_PUBLIC std::map<std::string,std::string> getCallMediaHandlerDetails(const std::string& id);
 DRING_PUBLIC bool getPluginsEnabled();
 DRING_PUBLIC void setPluginsEnabled(bool state);
-DRING_PUBLIC std::map<std::string, std::string> getCallMediaHandlerStatus();
-} // namespace DRing
+DRING_PUBLIC std::map<std::string,std::string> getCallMediaHandlerStatus();
+}
diff --git a/src/plugin/callservicesmanager.h b/src/plugin/callservicesmanager.h
index 2073e9c7ed..2981e314f8 100644
--- a/src/plugin/callservicesmanager.h
+++ b/src/plugin/callservicesmanager.h
@@ -21,6 +21,8 @@
 #pragma once
 // Utils
 #include "noncopyable.h"
+#include "logger.h"
+#include "manager.h"
 // Plugin Manager
 #include "pluginmanager.h"
 #include "streamdata.h"
@@ -33,12 +35,6 @@ using MediaHandlerPtr = std::unique_ptr<MediaHandler>;
 using CallMediaHandlerPtr = std::unique_ptr<CallMediaHandler>;
 using AVSubjectSPtr = std::weak_ptr<Observable<AVFrame*>>;
 
-struct MediaHandlerToggled
-{
-    std::string name = "";
-    std::string state = "false";
-};
-
 class CallServicesManager
 {
 public:
@@ -79,8 +75,24 @@ public:
     {
         // This guarantees unicity of subjects by id
         callAVsubjects.push_back(std::make_pair(data, subject));
-        auto inserted = callAVsubjects.back();
-        notifyAllAVSubject(inserted.first, inserted.second);
+    }
+
+    void clearAVSubject(const std::string& callID)
+    {
+        for (auto it = callAVsubjects.begin(); it != callAVsubjects.end();) {
+            if (it->first.id == callID) {
+                it = callAVsubjects.erase(it);
+            } else {
+                ++it;
+            }
+        }
+        for (auto& callMediaHandler : callMediaHandlers) {
+            if (mediaHandlerToggled_[getCallHandlerId(callMediaHandler.second)] == callID) {
+                callMediaHandler.first = false;
+                callMediaHandler.second->detach();
+                mediaHandlerToggled_[getCallHandlerId(callMediaHandler.second)] = "";
+            }
+        }
     }
 
     /**
@@ -137,17 +149,36 @@ public:
      */
     void toggleCallMediaHandler(const std::string& id, const bool toggle)
     {
-        for (auto& pair : callMediaHandlers) {
-            if (pair.second && getCallHandlerId(pair.second) == id) {
-                pair.first = toggle;
-                if (pair.first) {
-                    mediaHandlerToggled_.name = id;
-                    mediaHandlerToggled_.state = "true";
-                    listAvailableSubjects(pair.second);
-                } else {
-                    pair.second->detach();
-                    mediaHandlerToggled_.name = "";
-                    mediaHandlerToggled_.state = "false";
+        std::string callID = Manager::instance().getCurrentCallId();
+
+        if (toggle) {
+            for (auto& pair : mediaHandlerToggled_) {
+                if (pair.second == callID && pair.first != id) {
+                    toggleCallMediaHandler(pair.first, false);
+                }
+            }
+        }
+
+        if (id.empty())
+            return;
+
+        auto find = mediaHandlerToggled_.find(id);
+        if (find == mediaHandlerToggled_.end())
+            mediaHandlerToggled_[id] = "";
+
+        for (auto it = callAVsubjects.begin(); it != callAVsubjects.end(); ++it) {
+            if (it->first.id == callID) {
+                for (auto& pair : callMediaHandlers) {
+                    if (pair.second && getCallHandlerId(pair.second) == id) {
+                        pair.first = toggle;
+                        if (pair.first) {
+                            mediaHandlerToggled_[id] = callID;
+                            listAvailableSubjects(callID, pair.second);
+                        } else {
+                            pair.second->detach();
+                            mediaHandlerToggled_[id] = "";
+                        }
+                    }
                 }
             }
         }
@@ -170,13 +201,21 @@ public:
 
     std::map<std::string, std::string> getCallMediaHandlerStatus()
     {
-        return {{"name", mediaHandlerToggled_.name}, {"state", mediaHandlerToggled_.state}};
+        for (auto& pair : mediaHandlerToggled_) {
+            if (pair.second == Manager::instance().getCurrentCallId()) {
+                return {{"name", pair.first}};
+            }
+        }
+
+        return {{"name", ""}};
     }
 
     void setPreference(const std::string& key, const std::string& value, const std::string& scopeStr)
     {
         for (auto& pair : callMediaHandlers) {
-            if (pair.second && scopeStr.find(pair.second->getCallMediaHandlerDetails()["name"]) != std::string::npos) {
+            if (pair.second
+                && scopeStr.find(pair.second->getCallMediaHandlerDetails()["name"])
+                       != std::string::npos) {
                 pair.second->setPreferenceAttribute(key, value);
             }
         }
@@ -198,15 +237,29 @@ private:
         }
     }
 
+    void cleanCallAVSubjects()
+    {
+        // remove subjects from not available calls callAVsubjects
+        for (auto it = callAVsubjects.begin(); it != callAVsubjects.end();) {
+            std::vector<std::string> callids = jami::Manager::instance().getCallList();
+            if (std::find(callids.begin(), callids.end(), it->first.id) == callids.end()) {
+                it = callAVsubjects.erase(it);
+            } else {
+                ++it;
+            }
+        }
+    }
+
     /**
      * @brief listAvailableSubjects
      * @param callMediaHandlerPtr
      * This functions lets the call media handler component know which subjects are available
      */
-    void listAvailableSubjects(CallMediaHandlerPtr& callMediaHandlerPtr)
+    void listAvailableSubjects(const std::string& callID, CallMediaHandlerPtr& callMediaHandlerPtr)
     {
         for (auto it = callAVsubjects.begin(); it != callAVsubjects.end(); ++it) {
-            notifyAVSubject(callMediaHandlerPtr, it->first, it->second);
+            if (it->first.id == callID)
+                notifyAVSubject(callMediaHandlerPtr, it->first, it->second);
         }
     }
 
@@ -234,6 +287,7 @@ private:
      * whenever there is a new CallAVSubject like a video receive
      */
     std::list<std::pair<bool, CallMediaHandlerPtr>> callMediaHandlers;
+
     /**
      * @brief callAVsubjects
      * When there is a SIPCall, CallAVSubjects are created there
@@ -243,7 +297,7 @@ private:
      */
     std::list<std::pair<const StreamData, AVSubjectSPtr>> callAVsubjects;
 
-    MediaHandlerToggled mediaHandlerToggled_;
+    std::map<std::string, std::string> mediaHandlerToggled_;
 };
 
 } // namespace jami
diff --git a/src/plugin/jamipluginmanager.cpp b/src/plugin/jamipluginmanager.cpp
index 207f102745..69d84e403d 100644
--- a/src/plugin/jamipluginmanager.cpp
+++ b/src/plugin/jamipluginmanager.cpp
@@ -337,7 +337,11 @@ JamiPluginManager::unloadPlugin(const std::string& rootPath)
 void
 JamiPluginManager::togglePlugin(const std::string& rootPath, bool toggle)
 {
-    try {
+    //This function should not be used as is
+    //One should modify it to perform plugin install followed by load
+    //rootPath should be the jplpath!
+    try
+    {
         std::string soPath = getPluginDetails(rootPath).at("soPath");
         // remove the previous plugin object if it was registered
         pm_.destroyPluginComponents(soPath);
diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp
index 656400d09f..e606e9f14a 100644
--- a/src/sip/sipcall.cpp
+++ b/src/sip/sipcall.cpp
@@ -1188,6 +1188,12 @@ SIPCall::stopAllMedia()
 #ifdef ENABLE_VIDEO
     videortp_->stop();
 #endif
+#ifdef ENABLE_PLUGIN
+    jami::Manager::instance()
+        .getJamiPluginManager()
+        .getCallServicesManager()
+        .clearAVSubject(getCallId());
+#endif
 }
 
 void
-- 
GitLab