diff --git a/src/account.cpp b/src/account.cpp index 470bbb4720ffc4e8fc35bc1fa63443fd962e4c98..2082bc319ba9c0ea5e795829ca61c3b47f3d4900 100644 --- a/src/account.cpp +++ b/src/account.cpp @@ -41,6 +41,7 @@ #include "fileutils.h" #include "config/yamlparser.h" #include "system_codec_container.h" +#include "vcard.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @@ -65,10 +66,11 @@ namespace jami { // the data directory prefix that must be set at build time. const std::string Account::DEFAULT_USER_AGENT = Account::getDefaultUserAgent(); -Account::Account(const std::string& accountID) +Account::Account(const std::string& accountId) : rand(Manager::instance().getSeededRandomEngine()) - , accountID_(accountID) + , accountID_(accountId) , systemCodecContainer_(getSystemCodecContainer()) + , idPath_(fileutils::get_data_dir() / accountId) { // Initialize the codec order, used when creating a new account loadDefaultCodecs(); @@ -180,6 +182,20 @@ Account::getVolatileAccountDetails() const {libjami::Account::VolatileProperties::ACTIVE, active_ ? TRUE_STR : FALSE_STR}}; } +std::map<std::string, std::string> +Account::getProfileVcard() const +{ + try { + auto path = idPath_ / "profile.vcf"; + if (!std::filesystem::exists(path)) + return {}; + return vCard::utils::toMap(fileutils::loadTextFile(path)); + } catch (const std::exception& e) { + JAMI_ERROR("Error reading profile: {}", e.what()); + return {}; + } +} + bool Account::hasActiveCodec(MediaType mediaType) const { diff --git a/src/account.h b/src/account.h index 8db8c219fe700d2b37862488c0f26416692ab546..0a738f7b31d4527d6a3585c90d2f95dce3a64530 100644 --- a/src/account.h +++ b/src/account.h @@ -149,6 +149,8 @@ public: virtual std::string_view getAccountType() const = 0; + const std::filesystem::path& getPath() const { return idPath_; } + /** * Returns true if this is the IP2IP account */ @@ -208,7 +210,9 @@ public: virtual std::map<std::string, std::string> getNearbyPeers() const { return {}; } - virtual void updateProfile(const std::string& /*displayName*/, const std::string& /*avatar*/,const uint64_t& /*flag*/) {} + virtual void updateProfile(const std::string& /*displayName*/, const std::string& /*avatar*/,const uint64_t& /*flag*/) = 0; + + std::map<std::string, std::string> getProfileVcard() const; /** * Return the status corresponding to the token. @@ -479,6 +483,11 @@ protected: */ std::vector<std::shared_ptr<SystemCodecInfo>> accountCodecInfoList_; + /** + * path to account + */ + std::filesystem::path idPath_ {}; + /** * Ringtone .au file used for this account */ diff --git a/src/client/configurationmanager.cpp b/src/client/configurationmanager.cpp index b4d5098366efbd4c26786211189762c0acb10000..076526e7c314104c3e7660fb8d76e4c113f51c61 100644 --- a/src/client/configurationmanager.cpp +++ b/src/client/configurationmanager.cpp @@ -296,7 +296,9 @@ getNearbyPeers(const std::string& accountId) void updateProfile(const std::string& accountId,const std::string& displayName, const std::string& avatar,const uint64_t& flag) { - jami::Manager::instance().updateProfile(accountId, displayName, avatar, flag); + if (const auto acc = jami::Manager::instance().getAccount(accountId)){ + acc->updateProfile(displayName, avatar, flag); + } } int diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp index 96aaebab0cb01cd594d0b79001da5007293e0ab3..8cf817f862c24c2f23e82ab861a7fc0497ecb6c0 100644 --- a/src/jamidht/jamiaccount.cpp +++ b/src/jamidht/jamiaccount.cpp @@ -260,7 +260,6 @@ dhtStatusStr(dht::NodeStatus status) JamiAccount::JamiAccount(const std::string& accountId) : SIPAccountBase(accountId) - , idPath_(fileutils::get_data_dir() / accountId) , cachePath_(fileutils::get_cache_dir() / accountId) , dataPath_(cachePath_ / "values") , certStore_ {std::make_unique<dhtnet::tls::CertificateStore>(idPath_, Logger::dhtLogger())} @@ -3393,18 +3392,6 @@ JamiAccount::sendProfileToPeers() } } -std::map<std::string, std::string> -JamiAccount::getProfileVcard() const -{ - const auto& path = idPath_ / "profile.vcf"; - - if (!std::filesystem::exists(path)) { - return {}; - } - - return vCard::utils::toMap(fileutils::loadTextFile(path)); -} - void JamiAccount::updateProfile(const std::string& displayName, const std::string& avatar, diff --git a/src/jamidht/jamiaccount.h b/src/jamidht/jamiaccount.h index 316d2ed185089ad65744df8d7fad002d03a1673d..ca36fa26dca1ee9930aebe4ded3e8104ff51db16 100644 --- a/src/jamidht/jamiaccount.h +++ b/src/jamidht/jamiaccount.h @@ -119,8 +119,6 @@ public: return std::static_pointer_cast<JamiAccount const>(shared_from_this()); } - const std::filesystem::path& getPath() const { return idPath_; } - const JamiAccountConfig& config() const { return *static_cast<const JamiAccountConfig*>(&Account::config()); @@ -420,7 +418,6 @@ public: */ std::map<std::string, std::string> getNearbyPeers() const override; - std::map<std::string, std::string> getProfileVcard() const; void sendProfileToPeers(); /** @@ -708,7 +705,6 @@ private: const Uri& uri, const std::vector<libjami::MediaMap>& mediaList); std::shared_ptr<SIPCall> createSubCall(const std::shared_ptr<SIPCall>& mainCall); - std::filesystem::path idPath_ {}; std::filesystem::path cachePath_ {}; std::filesystem::path dataPath_ {}; diff --git a/src/manager.cpp b/src/manager.cpp index 46c062a9a8fdc6d870fbffa43332c3e578f5101e..a04b1336958819dd2509a9722e44983fde7aaaf6 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -3264,14 +3264,6 @@ Manager::getNearbyPeers(const std::string& accountID) return {}; } -void -Manager::updateProfile(const std::string& accountID,const std::string& displayName, const std::string& avatar,const uint64_t& flag) -{ - if (const auto acc = getAccount<JamiAccount>(accountID)) - acc->updateProfile(displayName,avatar,flag); -} - - void Manager::setDefaultModerator(const std::string& accountID, const std::string& peerURI, bool state) { diff --git a/src/manager.h b/src/manager.h index 898aedcc3c5f1765eb54fc939cddceb0cb8debc3..cc4fab98a0fa29faac9526d33a227487e7b68e33 100644 --- a/src/manager.h +++ b/src/manager.h @@ -811,8 +811,6 @@ public: std::map<std::string, std::string> getNearbyPeers(const std::string& accountID); - void updateProfile(const std::string& accountID,const std::string& displayName,const std::string& avatar,const uint64_t& flag); - #ifdef ENABLE_VIDEO /** * Create a new SinkClient instance, store it in an internal cache as a weak_ptr diff --git a/src/media/audio/audiolayer.cpp b/src/media/audio/audiolayer.cpp index 150ea80ac2984b0d2c14466d81611ea4861c44e4..98c50270cb0121931922cd1de73914ac17d9fcea 100644 --- a/src/media/audio/audiolayer.cpp +++ b/src/media/audio/audiolayer.cpp @@ -282,8 +282,7 @@ AudioLayer::getToRing(AudioFormat format, size_t writableSamples) auto fileformat = fileToPlay->getFormat(); bool resample = format != fileformat; - size_t readableSamples = resample ? (rational<size_t>(writableSamples, format.sample_rate) - * (size_t) fileformat.sample_rate) + size_t readableSamples = resample ? rational<size_t>(writableSamples * (size_t)fileformat.sample_rate, format.sample_rate) .real<size_t>() : writableSamples; diff --git a/src/media/media_decoder.cpp b/src/media/media_decoder.cpp index 3ca7b11a717dad9947e636b882c83d71b732dc33..9f0bb00169d8886b26eda529669d6ded81f7d003 100644 --- a/src/media/media_decoder.cpp +++ b/src/media/media_decoder.cpp @@ -706,7 +706,7 @@ MediaDecoder::decode(AVPacket& packet) if (emulateRate_ and packetTimestamp != AV_NOPTS_VALUE) { auto startTime = avStream_->start_time == AV_NOPTS_VALUE ? 0 : avStream_->start_time; rational<double> frame_time = rational<double>(getTimeBase()) - * (packetTimestamp - startTime); + * rational<double>(packetTimestamp - startTime); auto target_relative = static_cast<std::int64_t>(frame_time.real() * 1e6); auto target_absolute = startTime_ + target_relative; if (target_relative < seekTime_) { diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp index 46bdc76326d9b0ba934bc5ad47282b7f3ca7e244..db928c69c8656c87bf4c54c98100aeac0e8003da 100644 --- a/src/sip/sipaccount.cpp +++ b/src/sip/sipaccount.cpp @@ -23,6 +23,10 @@ #include "compiler_intrinsics.h" +#include "vcard.h" +#include "base64.h" +#include "fileutils.h" + #include "sdp.h" #include "sip/sipvoiplink.h" #include "sip/sipcall.h" @@ -141,6 +145,56 @@ SIPAccount::~SIPAccount() noexcept delete presence_; } +void +SIPAccount::updateProfile(const std::string& displayName, + const std::string& avatar, + const uint64_t& flag) +{ + auto vCardPath = idPath_ / "profile.vcf"; + + auto profile = getProfileVcard(); + if (profile.empty()) { + profile = vCard::utils::initVcard(); + } + profile["FN"] = displayName; + + if (flag == 0) { + const auto& avatarPath = std::filesystem::path(avatar); + if (std::filesystem::exists(avatarPath)) { + try { + const auto& base64 = jami::base64::encode(fileutils::loadFile(avatarPath)); + profile["PHOTO;ENCODING=BASE64;TYPE=PNG"] = base64; + } catch (const std::exception& e) { + JAMI_ERROR("Failed to load avatar: {}", e.what()); + } + } else if (avatarPath.empty()) { + profile["PHOTO;ENCODING=BASE64;TYPE=PNG"] = ""; + } + } else if (flag == 1) { + profile["PHOTO;ENCODING=BASE64;TYPE=PNG"] = avatar; + } + + // nothing happens to the profile photo if the avatarPath is invalid + // and not empty. So far it seems to be the best default behavior. + + const std::string& vCard = vCard::utils::toString(profile); + + try { + auto tmpPath = vCardPath; + tmpPath += ".tmp"; + std::ofstream file(tmpPath); + if (file.is_open()) { + file << vCard; + file.close(); + std::filesystem::rename(tmpPath, vCardPath); + } else { + JAMI_ERROR("Unable to open file for writing: {}", tmpPath); + } + } catch (const std::exception& e) { + JAMI_ERROR("Error writing profile: {}", e.what()); + } +} + std::shared_ptr<SIPCall> SIPAccount::newIncomingCall(const std::string& from UNUSED, const std::vector<libjami::MediaMap>& mediaList, diff --git a/src/sip/sipaccount.h b/src/sip/sipaccount.h index de676f6df86a63745029e6cf08986a190e9733e6..05cee9a1b4e679f2d9b485658e11a5fef71e493a 100644 --- a/src/sip/sipaccount.h +++ b/src/sip/sipaccount.h @@ -127,6 +127,11 @@ public: */ void loadConfig() override; + /** + * updates SIP account profile + */ + void updateProfile(const std::string& displayName, const std::string& avatar, const uint64_t& flag) override; + /** * Initialize the SIP voip link with the account parameters and send registration */