Commit 5856cf5a authored by Aline Gondim Santos's avatar Aline Gondim Santos Committed by Adrien Béraud
Browse files

plugins: add support to preferences per account

bump Plugin api version
bump Jami version

GitLab: #631
Change-Id: I8b8a9bbb05b3dd461bfafc02940441fda92b25c4
parent 91778a29
......@@ -31,9 +31,11 @@
<method name="getPluginPreferences" tp:name-for-bindings="getPluginPreferences">
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/>
<tp:added version="9.2.0"/>
<tp:added version="11.1.0"/>
<arg type="s" name="path" direction="in">
</arg>
<arg type="s" name="accountId" direction="in">
</arg>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/>
<arg type="aa{ss}" name="PluginPreferences" direction="out" tp:type="String_String_Map">
</arg>
......@@ -43,6 +45,8 @@
<tp:added version="9.2.0"/>
<arg type="s" name="path" direction="in">
</arg>
<arg type="s" name="accountId" direction="in">
</arg>
<arg type="s" name="key" direction="in">
</arg>
<arg type="s" name="value" direction="in">
......@@ -56,6 +60,8 @@
<tp:added version="9.2.0"/>
<arg type="s" name="path" direction="in">
</arg>
<arg type="s" name="accountId" direction="in">
</arg>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="MapStringString"/>
<arg type="a{ss}" name="preferencesValues" direction="out" tp:type="String_String_Map">
</arg>
......@@ -65,6 +71,8 @@
<tp:added version="9.2.0"/>
<arg type="s" name="path" direction="in">
</arg>
<arg type="s" name="accountId" direction="in">
</arg>
<arg type="b" name="reset" direction="out">
</arg>
</method>
......
......@@ -44,29 +44,33 @@ DBusPluginManagerInterface::getPluginDetails(const std::string& path)
}
std::vector<std::map<std::string, std::string>>
DBusPluginManagerInterface::getPluginPreferences(const std::string& path)
DBusPluginManagerInterface::getPluginPreferences(const std::string& path,
const std::string& accountId)
{
return DRing::getPluginPreferences(path);
return DRing::getPluginPreferences(path, accountId);
}
bool
DBusPluginManagerInterface::setPluginPreference(const std::string& path,
const std::string& accountId,
const std::string& key,
const std::string& value)
{
return DRing::setPluginPreference(path, key, value);
return DRing::setPluginPreference(path, accountId, key, value);
}
std::map<std::string, std::string>
DBusPluginManagerInterface::getPluginPreferencesValues(const std::string& path)
DBusPluginManagerInterface::getPluginPreferencesValues(const std::string& path,
const std::string& accountId)
{
return DRing::getPluginPreferencesValues(path);
return DRing::getPluginPreferencesValues(path, accountId);
}
bool
DBusPluginManagerInterface::resetPluginPreferencesValues(const std::string& path)
DBusPluginManagerInterface::resetPluginPreferencesValues(const std::string& path,
const std::string& accountId)
{
return DRing::resetPluginPreferencesValues(path);
return DRing::resetPluginPreferencesValues(path, accountId);
}
auto
......
......@@ -55,12 +55,15 @@ public:
bool loadPlugin(const std::string& path);
bool unloadPlugin(const std::string& path);
std::map<std::string, std::string> getPluginDetails(const std::string& path);
std::vector<std::map<std::string, std::string>> getPluginPreferences(const std::string& path);
std::vector<std::map<std::string, std::string>> getPluginPreferences(
const std::string& path, const std::string& accountId);
bool setPluginPreference(const std::string& path,
const std::string& accountId,
const std::string& key,
const std::string& value);
std::map<std::string, std::string> getPluginPreferencesValues(const std::string& path);
bool resetPluginPreferencesValues(const std::string& path);
std::map<std::string, std::string> getPluginPreferencesValues(const std::string& path,
const std::string& accountId);
bool resetPluginPreferencesValues(const std::string& path, const std::string& accountId);
std::vector<std::string> getInstalledPlugins();
std::vector<std::string> getLoadedPlugins();
int installPlugin(const std::string& jplPath, const bool& force);
......
......@@ -27,10 +27,10 @@ namespace DRing {
bool loadPlugin(const std::string& path);
bool unloadPlugin(const std::string& path);
std::map<std::string,std::string> getPluginDetails(const std::string& path);
std::vector<std::map<std::string,std::string>> getPluginPreferences(const std::string& path);
bool setPluginPreference(const std::string& path, const std::string& key, const std::string& value);
std::map<std::string,std::string> getPluginPreferencesValues(const std::string& path);
bool resetPluginPreferencesValues(const std::string& path);
std::vector<std::map<std::string,std::string>> getPluginPreferences(const std::string& path, const std::string& accountId);
bool setPluginPreference(const std::string& path, const std::string& accountId, const std::string& key, const std::string& value);
std::map<std::string,std::string> getPluginPreferencesValues(const std::string& path, const std::string& accountId);
bool resetPluginPreferencesValues(const std::string& path, const std::string& accountId);
std::vector<std::string> getInstalledPlugins();
std::vector<std::string> getLoadedPlugins();
int installPlugin(const std::string& jplPath, bool force);
......
......@@ -52,26 +52,35 @@ getPluginDetails(const std::string& path)
}
std::vector<std::map<std::string, std::string>>
getPluginPreferences(const std::string& path)
getPluginPreferences(const std::string& path, const std::string& accountId)
{
return jami::Manager::instance().getJamiPluginManager().getPluginPreferences(path);
return jami::Manager::instance().getJamiPluginManager().getPluginPreferences(path, accountId);
}
bool
setPluginPreference(const std::string& path, const std::string& key, const std::string& value)
setPluginPreference(const std::string& path,
const std::string& accountId,
const std::string& key,
const std::string& value)
{
return jami::Manager::instance().getJamiPluginManager().setPluginPreference(path, key, value);
return jami::Manager::instance().getJamiPluginManager().setPluginPreference(path,
accountId,
key,
value);
}
std::map<std::string, std::string>
getPluginPreferencesValues(const std::string& path)
getPluginPreferencesValues(const std::string& path, const std::string& accountId)
{
return jami::Manager::instance().getJamiPluginManager().getPluginPreferencesValuesMap(path);
return jami::Manager::instance().getJamiPluginManager().getPluginPreferencesValuesMap(path,
accountId);
}
bool
resetPluginPreferencesValues(const std::string& path)
resetPluginPreferencesValues(const std::string& path, const std::string& accountId)
{
return jami::Manager::instance().getJamiPluginManager().resetPluginPreferencesValuesMap(path);
return jami::Manager::instance()
.getJamiPluginManager()
.resetPluginPreferencesValuesMap(path, accountId);
}
std::vector<std::string>
......
......@@ -310,6 +310,8 @@ Conference::setLocalHostDefaultMediaSource()
void
Conference::createConfAVStreams()
{
std::string accountId = getAccountId();
auto audioMap = [](const std::shared_ptr<jami::MediaFrame>& m) -> AVFrame* {
return std::static_pointer_cast<AudioFrame>(m)->pointer();
};
......@@ -317,9 +319,9 @@ Conference::createConfAVStreams()
// Preview and Received
if ((audioMixer_ = jami::getAudioInput(getConfId()))) {
auto audioSubject = std::make_shared<MediaStreamSubject>(audioMap);
StreamData previewStreamData {getConfId(), false, StreamType::audio, getConfId()};
StreamData previewStreamData {getConfId(), false, StreamType::audio, getConfId(), accountId};
createConfAVStream(previewStreamData, *audioMixer_, audioSubject);
StreamData receivedStreamData {getConfId(), true, StreamType::audio, getConfId()};
StreamData receivedStreamData {getConfId(), true, StreamType::audio, getConfId(), accountId};
createConfAVStream(receivedStreamData, *audioMixer_, audioSubject);
}
......@@ -328,13 +330,13 @@ Conference::createConfAVStreams()
if (videoMixer_) {
// Review
auto receiveSubject = std::make_shared<MediaStreamSubject>(pluginVideoMap_);
StreamData receiveStreamData {getConfId(), true, StreamType::video, getConfId()};
StreamData receiveStreamData {getConfId(), true, StreamType::video, getConfId(), accountId};
createConfAVStream(receiveStreamData, *videoMixer_, receiveSubject);
// Preview
if (auto& videoPreview = videoMixer_->getVideoLocal()) {
auto previewSubject = std::make_shared<MediaStreamSubject>(pluginVideoMap_);
StreamData previewStreamData {getConfId(), false, StreamType::video, getConfId()};
StreamData previewStreamData {getConfId(), false, StreamType::video, getConfId(), accountId};
createConfAVStream(previewStreamData, *videoPreview, previewSubject);
}
}
......@@ -1024,7 +1026,7 @@ Conference::switchInput(const std::string& input)
// Preview
if (auto& videoPreview = mixer->getVideoLocal()) {
auto previewSubject = std::make_shared<MediaStreamSubject>(pluginVideoMap_);
StreamData previewStreamData {getConfId(), false, StreamType::video, getConfId()};
StreamData previewStreamData {getConfId(), false, StreamType::video, getConfId(), getAccountId()};
createConfAVStream(previewStreamData, *videoPreview, previewSubject, true);
}
#endif
......
......@@ -38,12 +38,15 @@ DRING_PUBLIC bool loadPlugin(const std::string& path);
DRING_PUBLIC bool unloadPlugin(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);
const std::string& path, const std::string& accountId);
DRING_PUBLIC bool setPluginPreference(const std::string& path,
const std::string& accountId,
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::map<std::string, std::string> getPluginPreferencesValues(
const std::string& path, const std::string& accountId);
DRING_PUBLIC bool resetPluginPreferencesValues(const std::string& path,
const std::string& accountId);
DRING_PUBLIC std::vector<std::string> getInstalledPlugins();
DRING_PUBLIC std::vector<std::string> getLoadedPlugins();
DRING_PUBLIC int installPlugin(const std::string& jplPath, bool force);
......
......@@ -2789,13 +2789,6 @@ Manager::loadAccountMap(const YAML::Node& node)
#endif
#ifdef ENABLE_PLUGIN
pluginPreferences.unserialize(node);
if (pluginPreferences.getPluginsEnabled()) {
std::vector<std::string> loadedPlugins = pluginPreferences.getLoadedPlugins();
for (const std::string& plugin : loadedPlugins) {
jami::Manager::instance().getJamiPluginManager().loadPlugin(plugin);
}
}
#endif
} catch (const YAML::Exception& e) {
JAMI_ERR("%s: Preferences node unserialize error: ", e.what());
......@@ -2849,6 +2842,15 @@ Manager::loadAccountMap(const YAML::Node& node)
}
cv.wait(l, [&remaining] { return remaining == 0; });
#ifdef ENABLE_PLUGIN
if (pluginPreferences.getPluginsEnabled()) {
std::vector<std::string> loadedPlugins = pluginPreferences.getLoadedPlugins();
for (const std::string& plugin : loadedPlugins) {
jami::Manager::instance().getJamiPluginManager().loadPlugin(plugin);
}
}
#endif
return errorCount;
}
......
......@@ -292,6 +292,7 @@ endif
if conf.get('ENABLE_PLUGIN')
libjami_sources += files(
'client/plugin_manager_interface.cpp',
'plugin/preferenceservicesmanager.cpp',
'plugin/callservicesmanager.cpp',
'plugin/chatservicesmanager.cpp',
'plugin/jamipluginmanager.cpp',
......
......@@ -7,10 +7,13 @@ list (APPEND Source_Files__plugin
"${CMAKE_CURRENT_SOURCE_DIR}/pluginmanager.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pluginpreferencesutils.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pluginsutils.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/preferenceservicesmanager.h"
"${CMAKE_CURRENT_SOURCE_DIR}/preferenceservicesmanager.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/callservicesmanager.h"
"${CMAKE_CURRENT_SOURCE_DIR}/callservicesmanager.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/chatservicesmanager.h"
"${CMAKE_CURRENT_SOURCE_DIR}/chatservicesmanager.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/preferencehandler.h"
"${CMAKE_CURRENT_SOURCE_DIR}/chathandler.h"
"${CMAKE_CURRENT_SOURCE_DIR}/jamiplugin.h"
"${CMAKE_CURRENT_SOURCE_DIR}/jamipluginmanager.h"
......
......@@ -3,7 +3,9 @@ if ENABLE_PLUGIN
noinst_LTLIBRARIES += libplugin.la
noinst_HEADERS += \
./plugin/preferenceservicesmanager.h \
./plugin/callservicesmanager.h \
./plugin/preferencehandler.h \
./plugin/chathandler.h \
./plugin/chatservicesmanager.h \
./plugin/jamiplugin.h \
......@@ -22,7 +24,8 @@ libplugin_la_SOURCES = \
./plugin/pluginpreferencesutils.cpp \
./plugin/pluginsutils.cpp \
./plugin/chatservicesmanager.cpp \
./plugin/callservicesmanager.cpp
./plugin/callservicesmanager.cpp \
./plugin/preferenceservicesmanager.cpp
libring_la_LIBADD += libplugin.la
......
......@@ -61,7 +61,8 @@ CallServicesManager::createAVSubject(const StreamData& data, AVSubjectSPtr subje
// toggle is true if we should automatically activate the MediaHandler.
bool toggle = PluginPreferencesUtils::getAlwaysPreference(
callMediaHandler->id().substr(0, found),
callMediaHandler->getCallMediaHandlerDetails().at("name"));
callMediaHandler->getCallMediaHandlerDetails().at("name"),
data.source);
// toggle may be overwritten if the MediaHandler was previously activated/deactivated
// for the given call.
for (const auto& toggledMediaHandlerPair : mediaHandlerToggled_[data.id]) {
......
......@@ -147,7 +147,8 @@ ChatServicesManager::publishMessage(pluginMessagePtr message)
std::size_t found = chatHandler->id().find_last_of(DIR_SEPARATOR_CH);
// toggle is true if we should automatically activate the ChatHandler.
bool toggle = PluginPreferencesUtils::getAlwaysPreference(chatHandler->id().substr(0, found),
chatHandlerName);
chatHandlerName,
message->accountId);
// toggle is overwritten if we have previously activated/deactivated the ChatHandler
// for the given conversation.
auto allowedIt = chatAllowDenySet.find(chatHandlerName);
......
......@@ -38,8 +38,8 @@
#define JAMI_PLUGIN_ABI_VERSION 1 // 0 doesn't exist, considered as error
// JAMI_PLUGIN_API_VERSION reflects changes in Services Managers
// (CallServicesManager and ChatServicesMangers) and in JAMI_PluginAPI.
#define JAMI_PLUGIN_API_VERSION 1 // 0 doesn't exist, considered as error
// (CallServicesManager, ChatServicesMansge, and PreferenceServicesManagers) and in JAMI_PluginAPI.
#define JAMI_PLUGIN_API_VERSION 2 // 0 doesn't exist, considered as error
C_INTERFACE_START;
......
......@@ -79,9 +79,11 @@ JamiPluginManager::getInstalledPlugins()
std::for_each(pluginsPaths.begin(), pluginsPaths.end(), [&pluginsPath](std::string& x) {
x = pluginsPath + DIR_SEPARATOR_CH + x;
});
auto returnIterator = std::remove_if(pluginsPaths.begin(), pluginsPaths.end(), [](const std::string& path) {
return !PluginUtils::checkPluginValidity(path);
});
auto returnIterator = std::remove_if(pluginsPaths.begin(),
pluginsPaths.end(),
[](const std::string& path) {
return !PluginUtils::checkPluginValidity(path);
});
pluginsPaths.erase(returnIterator, std::end(pluginsPaths));
// Gets plugins installed in non standard path
......@@ -106,8 +108,8 @@ JamiPluginManager::installPlugin(const std::string& jplPath, bool force)
if (name.empty())
return 0;
const std::string& version = manifestMap["version"];
std::string destinationDir {fileutils::get_data_dir() + DIR_SEPARATOR_CH
+ "plugins" + DIR_SEPARATOR_CH + name};
std::string destinationDir {fileutils::get_data_dir() + DIR_SEPARATOR_CH + "plugins"
+ DIR_SEPARATOR_CH + name};
// Find if there is an existing version of this plugin
const auto alreadyInstalledManifestMap = PluginUtils::parseManifestFile(
PluginUtils::manifestPath(destinationDir));
......@@ -163,6 +165,10 @@ JamiPluginManager::uninstallPlugin(const std::string& rootPath)
return -1;
}
}
for (const auto& accId : jami::Manager::instance().getAccountList())
fileutils::removeAll(fileutils::get_data_dir() + DIR_SEPARATOR_CH + accId
+ DIR_SEPARATOR_CH + "plugins" + DIR_SEPARATOR_CH
+ detailsIt->second.at("name"));
pluginDetailsMap_.erase(detailsIt);
}
return fileutils::removeAll(rootPath);
......@@ -223,34 +229,49 @@ JamiPluginManager::getLoadedPlugins() const
}
std::vector<std::map<std::string, std::string>>
JamiPluginManager::getPluginPreferences(const std::string& rootPath)
JamiPluginManager::getPluginPreferences(const std::string& rootPath, const std::string& accountId)
{
return PluginPreferencesUtils::getPreferences(rootPath);
return PluginPreferencesUtils::getPreferences(rootPath, accountId);
}
bool
JamiPluginManager::setPluginPreference(const std::string& rootPath,
const std::string& accountId,
const std::string& key,
const std::string& value)
{
std::string acc = accountId;
// If we try to change a preference value linked to an account
// but that preference is global, we must ignore accountId and
// change the preference for every account
if (!accountId.empty()) {
// Get global preferences
auto preferences = PluginPreferencesUtils::getPreferences(rootPath, "");
// Check if the preference we want to change is global
auto it = std::find_if(preferences.cbegin(),
preferences.cend(),
[key](const std::map<std::string, std::string>& preference) {
return preference.at("key") == key;
});
// Ignore accountId if global preference
if (it != preferences.cend())
acc.clear();
}
std::map<std::string, std::string> pluginUserPreferencesMap
= PluginPreferencesUtils::getUserPreferencesValuesMap(rootPath);
= PluginPreferencesUtils::getUserPreferencesValuesMap(rootPath, acc);
std::map<std::string, std::string> pluginPreferencesMap
= PluginPreferencesUtils::getPreferencesValuesMap(rootPath);
= PluginPreferencesUtils::getPreferencesValuesMap(rootPath, acc);
std::vector<std::map<std::string, std::string>> preferences
= PluginPreferencesUtils::getPreferences(rootPath);
// If any plugin handler is active we may have to reload it
bool force {pm_.checkLoadedPlugin(rootPath)};
// We check if the preference is modified without having to reload plugin
for (auto& preference : preferences) {
if (!preference["key"].compare(key)) {
force &= callsm_.setPreference(key, value, rootPath);
force &= chatsm_.setPreference(key, value, rootPath);
break;
}
}
force &= preferencesm_.setPreference(key, value, rootPath, acc);
force &= callsm_.setPreference(key, value, rootPath);
force &= chatsm_.setPreference(key, value, rootPath);
if (force)
unloadPlugin(rootPath);
......@@ -258,8 +279,8 @@ JamiPluginManager::setPluginPreference(const std::string& rootPath,
auto find = pluginPreferencesMap.find(key);
if (find != pluginPreferencesMap.end()) {
pluginUserPreferencesMap[key] = value;
const std::string preferencesValuesFilePath = PluginPreferencesUtils::valuesFilePath(
rootPath);
const std::string preferencesValuesFilePath
= PluginPreferencesUtils::valuesFilePath(rootPath, acc);
std::lock_guard<std::mutex> guard(fileutils::getFileLock(preferencesValuesFilePath));
std::ofstream fs(preferencesValuesFilePath, std::ios::binary);
if (!fs.good()) {
......@@ -285,19 +306,23 @@ JamiPluginManager::setPluginPreference(const std::string& rootPath,
}
std::map<std::string, std::string>
JamiPluginManager::getPluginPreferencesValuesMap(const std::string& rootPath)
JamiPluginManager::getPluginPreferencesValuesMap(const std::string& rootPath,
const std::string& accountId)
{
return PluginPreferencesUtils::getPreferencesValuesMap(rootPath);
return PluginPreferencesUtils::getPreferencesValuesMap(rootPath, accountId);
}
bool
JamiPluginManager::resetPluginPreferencesValuesMap(const std::string& rootPath)
JamiPluginManager::resetPluginPreferencesValuesMap(const std::string& rootPath,
const std::string& accountId)
{
bool acc {accountId.empty()};
bool loaded {pm_.checkLoadedPlugin(rootPath)};
if (loaded)
if (loaded && acc)
unloadPlugin(rootPath);
auto status = PluginPreferencesUtils::resetPreferencesValuesMap(rootPath);
if (loaded) {
auto status = PluginPreferencesUtils::resetPreferencesValuesMap(rootPath, accountId);
preferencesm_.resetPreferences(rootPath, accountId);
if (loaded && acc) {
loadPlugin(rootPath);
}
return status;
......@@ -320,5 +345,23 @@ JamiPluginManager::registerServices()
dataPath->assign(PluginUtils::dataPath(plugin->getPath()));
return 0;
});
// getPluginAccPreferences is a service that allows plugins to load saved per account preferences.
auto getPluginAccPreferences = [](const DLPlugin* plugin, void* data) {
const auto path = PluginUtils::getRootPathFromSoPath(plugin->getPath());
auto preferencesPtr {(static_cast<PreferencesMap*>(data))};
if (!preferencesPtr)
return -1;
preferencesPtr->emplace("default",
PluginPreferencesUtils::getPreferencesValuesMap(path, "default"));
for (const auto& accId : jami::Manager::instance().getAccountList())
preferencesPtr->emplace(accId,
PluginPreferencesUtils::getPreferencesValuesMap(path, accId));
return 0;
};
pm_.registerService("getPluginAccPreferences", getPluginAccPreferences);
}
} // namespace jami
......@@ -26,6 +26,7 @@
#include "callservicesmanager.h"
#include "chatservicesmanager.h"
#include "preferenceservicesmanager.h"
#include <vector>
#include <map>
......@@ -34,6 +35,8 @@
namespace jami {
using PreferencesMap = std::map<std::string, std::map<std::string, std::string>>;
/**
* @class JamiPluginManager
* @brief This class provides an interface to functions exposed to the
......@@ -45,6 +48,7 @@ public:
JamiPluginManager()
: callsm_ {pm_}
, chatsm_ {pm_}
, preferencesm_ {pm_}
{
registerServices();
}
......@@ -102,39 +106,48 @@ public:
/**
* @brief Returns contents of plugin's preferences.json file
* @param rootPath
* @param accountId
*/
std::vector<std::map<std::string, std::string>> getPluginPreferences(const std::string& rootPath);
std::vector<std::map<std::string, std::string>> getPluginPreferences(
const std::string& rootPath, const std::string& accountId);
/**
* @brief Returns a Map with preferences keys and values.
* @param rootPath
* @param accountId
*/
std::map<std::string, std::string> getPluginPreferencesValuesMap(const std::string& rootPath);
std::map<std::string, std::string> getPluginPreferencesValuesMap(const std::string& rootPath,
const std::string& accountId);
/**
* @brief Modifies a preference value by saving it to a preferences.msgpack.
* Plugin is reloaded only if the preference cannot take effect immediately.
* In other words, if we have to reload plugin so that preference may take effect.
* @param rootPath
* @param accountId
* @param key
* @param value
* @return True if success
*/
bool setPluginPreference(const std::string& rootPath,
const std::string& accountId,
const std::string& key,
const std::string& value);
/**
* @brief Reset plugin's preferences values to their defaultValues
* @param rootPath
* @param accountId
* @return True if success.
*/
bool resetPluginPreferencesValuesMap(const std::string& rootPath);
bool resetPluginPreferencesValuesMap(const std::string& rootPath, const std::string& accountId);
CallServicesManager& getCallServicesManager() { return callsm_; }
ChatServicesManager& getChatServicesManager() { return chatsm_; }
PreferenceServicesManager& getPreferenceServicesManager() { return preferencesm_; }
private:
NON_COPYABLE(JamiPluginManager);
......@@ -152,5 +165,6 @@ private:
// Services instances
CallServicesManager callsm_;
ChatServicesManager chatsm_;
PreferenceServicesManager preferencesm_;
};
} // namespace jami
......@@ -150,6 +150,7 @@ PluginManager::callPluginInitFunction(const std::string& path)
if (!exitFunc) {
JAMI_ERR() << "Plugin: init failed";
// emit signal with error message to let user know that jamid could not load plugin
returnValue = false;
} else {
returnValue = true;
......