LCOV - code coverage report
Current view: top level - foo/src - preferences.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 241 277 87.0 %
Date: 2026-04-01 09:29:43 Functions: 23 29 79.3 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2004-2026 Savoir-faire Linux Inc.
       3             :  *
       4             :  *  This program is free software: you can redistribute it and/or modify
       5             :  *  it under the terms of the GNU General Public License as published by
       6             :  *  the Free Software Foundation, either version 3 of the License, or
       7             :  *  (at your option) any later version.
       8             :  *
       9             :  *  This program is distributed in the hope that it will be useful,
      10             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      12             :  *  GNU General Public License for more details.
      13             :  *
      14             :  *  You should have received a copy of the GNU General Public License
      15             :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #ifdef HAVE_CONFIG_H
      19             : #include "config.h"
      20             : #endif
      21             : 
      22             : #include "preferences.h"
      23             : #include "logger.h"
      24             : #include "audio/audiolayer.h"
      25             : 
      26             : #if HAVE_AAUDIO
      27             : #include "audio/aaudio/aaudiolayer.h"
      28             : #else
      29             : #if HAVE_ALSA
      30             : #include "audio/alsa/alsalayer.h"
      31             : #endif
      32             : #if HAVE_JACK
      33             : #include "audio/jack/jacklayer.h"
      34             : #endif
      35             : #if HAVE_PULSE
      36             : #include "audio/pulseaudio/pulselayer.h"
      37             : #endif
      38             : #if HAVE_COREAUDIO
      39             : #ifdef __APPLE__
      40             : #include <TargetConditionals.h>
      41             : #endif
      42             : #if TARGET_OS_IOS
      43             : #include "audio/coreaudio/ios/corelayer.h"
      44             : #else
      45             : #include "audio/coreaudio/osx/corelayer.h"
      46             : #endif /* TARGET_OS_IOS */
      47             : #endif /* HAVE_COREAUDIO */
      48             : #if HAVE_PORTAUDIO
      49             : #include "audio/portaudio/portaudiolayer.h"
      50             : #endif
      51             : #endif /* HAVE_AAUDIO */
      52             : 
      53             : #ifdef ENABLE_VIDEO
      54             : #include "client/videomanager.h"
      55             : #endif
      56             : 
      57             : #pragma GCC diagnostic push
      58             : #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
      59             : #include <yaml-cpp/yaml.h>
      60             : #pragma GCC diagnostic pop
      61             : 
      62             : #include "config/yamlparser.h"
      63             : #include "connectivity/sip_utils.h"
      64             : #include <algorithm>
      65             : #include <stdexcept>
      66             : #include "fileutils.h"
      67             : 
      68             : namespace jami {
      69             : 
      70             : using yaml_utils::parseValue;
      71             : 
      72             : constexpr const char* const Preferences::CONFIG_LABEL;
      73             : const char* const Preferences::DFT_ZONE = "North America";
      74             : const char* const Preferences::REGISTRATION_EXPIRE_KEY = "registrationexpire";
      75             : constexpr std::string_view DEFAULT_CONFERENCE_RESOLUTION {"1280x720"};
      76             : 
      77             : // general preferences
      78             : static constexpr const char* ORDER_KEY {"order"};
      79             : static constexpr const char* PENDING_ACCOUNTS_KEY {"pendingAccounts"};
      80             : static constexpr const char* AUDIO_API_KEY {"audioApi"};
      81             : static constexpr const char* HISTORY_LIMIT_KEY {"historyLimit"};
      82             : static constexpr const char* RINGING_TIMEOUT {"ringingTimeout"};
      83             : static constexpr const char* HISTORY_MAX_CALLS_KEY {"historyMaxCalls"};
      84             : static constexpr const char* ZONE_TONE_CHOICE_KEY {"zoneToneChoice"};
      85             : static constexpr const char* PORT_NUM_KEY {"portNum"};
      86             : static constexpr const char* SEARCH_BAR_DISPLAY_KEY {"searchBarDisplay"};
      87             : static constexpr const char* MD5_HASH_KEY {"md5Hash"};
      88             : 
      89             : // voip preferences
      90             : constexpr const char* const VoipPreference::CONFIG_LABEL;
      91             : static constexpr const char* PLAY_DTMF_KEY {"playDtmf"};
      92             : static constexpr const char* PLAY_TONES_KEY {"playTones"};
      93             : static constexpr const char* PULSE_LENGTH_KEY {"pulseLength"};
      94             : 
      95             : // audio preferences
      96             : constexpr const char* const AudioPreference::CONFIG_LABEL;
      97             : static constexpr const char* ALSAMAP_KEY {"alsa"};
      98             : static constexpr const char* PULSEMAP_KEY {"pulse"};
      99             : static constexpr const char* PORTAUDIO_KEY {"portaudio"};
     100             : static constexpr const char* CARDIN_KEY {"cardIn"};
     101             : static constexpr const char* CARDOUT_KEY {"cardOut"};
     102             : static constexpr const char* CARLIBJAMI_KEY {"cardRing"};
     103             : static constexpr const char* PLUGIN_KEY {"plugin"};
     104             : static constexpr const char* SMPLRATE_KEY {"smplRate"};
     105             : static constexpr const char* DEVICE_PLAYBACK_KEY {"devicePlayback"};
     106             : static constexpr const char* DEVICE_RECORD_KEY {"deviceRecord"};
     107             : static constexpr const char* DEVICE_RINGTONE_KEY {"deviceRingtone"};
     108             : static constexpr const char* RECORDPATH_KEY {"recordPath"};
     109             : static constexpr const char* ALWAYS_RECORDING_KEY {"alwaysRecording"};
     110             : static constexpr const char* VOLUMEMIC_KEY {"volumeMic"};
     111             : static constexpr const char* VOLUMESPKR_KEY {"volumeSpkr"};
     112             : static constexpr const char* AUDIO_PROCESSOR_KEY {"audioProcessor"};
     113             : static constexpr const char* NOISE_REDUCE_KEY {"noiseReduce"};
     114             : static constexpr const char* AGC_KEY {"automaticGainControl"};
     115             : static constexpr const char* CAPTURE_MUTED_KEY {"captureMuted"};
     116             : static constexpr const char* PLAYBACK_MUTED_KEY {"playbackMuted"};
     117             : static constexpr const char* VAD_KEY {"voiceActivityDetection"};
     118             : static constexpr const char* ECHO_CANCEL_KEY {"echoCancel"};
     119             : 
     120             : #ifdef ENABLE_VIDEO
     121             : // video preferences
     122             : constexpr const char* const VideoPreferences::CONFIG_LABEL;
     123             : static constexpr const char* DECODING_ACCELERATED_KEY {"decodingAccelerated"};
     124             : static constexpr const char* ENCODING_ACCELERATED_KEY {"encodingAccelerated"};
     125             : static constexpr const char* RECORD_PREVIEW_KEY {"recordPreview"};
     126             : static constexpr const char* RECORD_QUALITY_KEY {"recordQuality"};
     127             : static constexpr const char* CONFERENCE_RESOLUTION_KEY {"conferenceResolution"};
     128             : #endif
     129             : 
     130             : #ifdef ENABLE_PLUGIN
     131             : // plugin preferences
     132             : constexpr const char* const PluginPreferences::CONFIG_LABEL;
     133             : static constexpr const char* JAMI_PLUGIN_KEY {"pluginsEnabled"};
     134             : static constexpr const char* JAMI_PLUGINS_INSTALLED_KEY {"installedPlugins"};
     135             : static constexpr const char* JAMI_PLUGINS_LOADED_KEY {"loadedPlugins"};
     136             : #endif
     137             : 
     138             : static constexpr int PULSE_LENGTH_DEFAULT {250}; /** Default DTMF length */
     139             : #ifndef _MSC_VER
     140             : static constexpr const char* ALSA_DFT_CARD {"0"}; /** Default sound card index */
     141             : #else
     142             : static constexpr const char* ALSA_DFT_CARD {"-1"}; /** Default sound card index (Portaudio) */
     143             : #endif // _MSC_VER
     144             : 
     145          38 : Preferences::Preferences()
     146          38 :     : accountOrder_("")
     147          38 :     , historyLimit_(0)
     148          38 :     , historyMaxCalls_(20)
     149          38 :     , ringingTimeout_(30)
     150          38 :     , zoneToneChoice_(DFT_ZONE) // DFT_ZONE
     151          38 :     , portNum_(sip_utils::DEFAULT_SIP_PORT)
     152          38 :     , searchBarDisplay_(true)
     153          76 :     , md5Hash_(false)
     154          38 : {}
     155             : 
     156             : void
     157        2449 : Preferences::verifyAccountOrder(const std::vector<std::string>& accountIDs)
     158             : {
     159        2449 :     std::vector<std::string> tokens;
     160        2449 :     std::string token;
     161        2449 :     bool drop = false;
     162             : 
     163      104380 :     for (const auto c : accountOrder_) {
     164      101931 :         if (c != '/') {
     165       95934 :             token += c;
     166             :         } else {
     167        5997 :             if (find(accountIDs.begin(), accountIDs.end(), token) != accountIDs.end())
     168        5993 :                 tokens.push_back(token);
     169             :             else {
     170           4 :                 JAMI_DBG("Dropping nonexistent account %s", token.c_str());
     171           4 :                 drop = true;
     172             :             }
     173        5997 :             token.clear();
     174             :         }
     175             :     }
     176             : 
     177        2449 :     if (drop) {
     178           2 :         accountOrder_.clear();
     179           3 :         for (const auto& t : tokens)
     180           1 :             accountOrder_ += t + '/';
     181             :     }
     182        2449 : }
     183             : 
     184             : void
     185         795 : Preferences::addAccount(const std::string& newAccountID)
     186             : {
     187             :     // Add the newly created account in the account order list
     188         795 :     if (not accountOrder_.empty())
     189         532 :         accountOrder_.insert(0, newAccountID + "/");
     190             :     else
     191         263 :         accountOrder_ = newAccountID + "/";
     192         795 : }
     193             : 
     194             : void
     195         795 : Preferences::removeAccount(const std::string& oldAccountID)
     196             : {
     197             :     // include the slash since we don't want to remove a partial match
     198         795 :     const size_t start = accountOrder_.find(oldAccountID + "/");
     199         795 :     if (start != std::string::npos)
     200         795 :         accountOrder_.erase(start, oldAccountID.length() + 1);
     201         795 : }
     202             : 
     203             : bool
     204          35 : Preferences::isAccountPending(const std::string& accountId) const
     205             : {
     206          35 :     return pendingAccountIds_.count(accountId) > 0;
     207             : }
     208             : 
     209             : bool
     210         771 : Preferences::addPendingAccountId(const std::string& accountId)
     211             : {
     212         771 :     if (accountId.empty())
     213           0 :         return false;
     214         771 :     return pendingAccountIds_.insert(accountId).second;
     215             : }
     216             : 
     217             : bool
     218        1584 : Preferences::removePendingAccountId(const std::string& accountId)
     219             : {
     220        1584 :     if (accountId.empty())
     221           0 :         return false;
     222        1584 :     return pendingAccountIds_.erase(accountId) > 0;
     223             : }
     224             : 
     225             : void
     226        2449 : Preferences::serialize(YAML::Emitter& out) const
     227             : {
     228        2449 :     out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap;
     229             : 
     230        2449 :     out << YAML::Key << HISTORY_LIMIT_KEY << YAML::Value << historyLimit_;
     231        2449 :     out << YAML::Key << RINGING_TIMEOUT << YAML::Value << ringingTimeout_;
     232        2449 :     out << YAML::Key << HISTORY_MAX_CALLS_KEY << YAML::Value << historyMaxCalls_;
     233        2449 :     out << YAML::Key << MD5_HASH_KEY << YAML::Value << md5Hash_;
     234        2449 :     out << YAML::Key << ORDER_KEY << YAML::Value << accountOrder_;
     235        2449 :     out << YAML::Key << PORT_NUM_KEY << YAML::Value << portNum_;
     236        2449 :     out << YAML::Key << SEARCH_BAR_DISPLAY_KEY << YAML::Value << searchBarDisplay_;
     237        2449 :     out << YAML::Key << ZONE_TONE_CHOICE_KEY << YAML::Value << zoneToneChoice_;
     238        2449 :     out << YAML::Key << PENDING_ACCOUNTS_KEY << YAML::Value << YAML::BeginSeq;
     239        5228 :     for (const auto& accountId : pendingAccountIds_)
     240        2779 :         out << accountId;
     241        2449 :     out << YAML::EndSeq;
     242        2449 :     out << YAML::EndMap;
     243        2449 : }
     244             : 
     245             : void
     246          35 : Preferences::unserialize(const YAML::Node& in)
     247             : {
     248          35 :     const auto& node = in[CONFIG_LABEL];
     249             : 
     250          35 :     parseValue(node, ORDER_KEY, accountOrder_);
     251          29 :     parseValue(node, HISTORY_LIMIT_KEY, historyLimit_);
     252          29 :     parseValue(node, RINGING_TIMEOUT, ringingTimeout_);
     253          29 :     parseValue(node, HISTORY_MAX_CALLS_KEY, historyMaxCalls_);
     254          29 :     parseValue(node, ZONE_TONE_CHOICE_KEY, zoneToneChoice_);
     255          29 :     parseValue(node, PORT_NUM_KEY, portNum_);
     256          29 :     parseValue(node, SEARCH_BAR_DISPLAY_KEY, searchBarDisplay_);
     257          29 :     parseValue(node, MD5_HASH_KEY, md5Hash_);
     258             : 
     259          29 :     pendingAccountIds_.clear();
     260          29 :     if (const auto& pending = node[PENDING_ACCOUNTS_KEY]; pending && pending.IsSequence()) {
     261          29 :         for (const auto& entry : pending) {
     262             :             try {
     263           0 :                 pendingAccountIds_.insert(entry.as<std::string>());
     264           0 :             } catch (const YAML::Exception& e) {
     265           0 :                 JAMI_WARN("[config] Unable to read pending account id: %s", e.what());
     266           0 :             }
     267          29 :         }
     268          29 :     }
     269          35 : }
     270             : 
     271          38 : VoipPreference::VoipPreference()
     272          38 :     : playDtmf_(true)
     273          38 :     , playTones_(true)
     274          38 :     , pulseLength_(PULSE_LENGTH_DEFAULT)
     275          38 : {}
     276             : 
     277             : void
     278        2449 : VoipPreference::serialize(YAML::Emitter& out) const
     279             : {
     280        2449 :     out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap;
     281        2449 :     out << YAML::Key << PLAY_DTMF_KEY << YAML::Value << playDtmf_;
     282        2449 :     out << YAML::Key << PLAY_TONES_KEY << YAML::Value << playTones_;
     283        2449 :     out << YAML::Key << PULSE_LENGTH_KEY << YAML::Value << pulseLength_;
     284        2449 :     out << YAML::EndMap;
     285        2449 : }
     286             : 
     287             : void
     288          29 : VoipPreference::unserialize(const YAML::Node& in)
     289             : {
     290          29 :     const auto& node = in[CONFIG_LABEL];
     291          29 :     parseValue(node, PLAY_DTMF_KEY, playDtmf_);
     292          29 :     parseValue(node, PLAY_TONES_KEY, playTones_);
     293          29 :     parseValue(node, PULSE_LENGTH_KEY, pulseLength_);
     294          29 : }
     295             : 
     296          38 : AudioPreference::AudioPreference()
     297          38 :     : audioApi_(PULSEAUDIO_API_STR)
     298          38 :     , alsaCardin_(atoi(ALSA_DFT_CARD))
     299          38 :     , alsaCardout_(atoi(ALSA_DFT_CARD))
     300          38 :     , alsaCardRingtone_(atoi(ALSA_DFT_CARD))
     301          38 :     , alsaPlugin_("default")
     302          38 :     , alsaSmplrate_(44100)
     303          38 :     , pulseDevicePlayback_("")
     304          38 :     , pulseDeviceRecord_("")
     305          38 :     , pulseDeviceRingtone_("")
     306          38 :     , recordpath_("")
     307          38 :     , alwaysRecording_(false)
     308          38 :     , volumemic_(1.0)
     309          38 :     , volumespkr_(1.0)
     310          38 :     , audioProcessor_("webrtc")
     311          38 :     , denoise_("auto")
     312          38 :     , agcEnabled_(true)
     313          38 :     , vadEnabled_(true)
     314          38 :     , echoCanceller_("auto")
     315          38 :     , captureMuted_(false)
     316          76 :     , playbackMuted_(false)
     317          38 : {}
     318             : 
     319             : #if HAVE_ALSA
     320             : 
     321             : static const int ALSA_DFT_CARD_ID = 0; // Index of the default soundcard
     322             : 
     323             : static void
     324          96 : checkSoundCard(int& card, AudioDeviceType type)
     325             : {
     326          96 :     if (not AlsaLayer::soundCardIndexExists(card, type)) {
     327          96 :         JAMI_WARN(" Card with index %d doesn't exist or is unusable.", card);
     328          96 :         card = ALSA_DFT_CARD_ID;
     329             :     }
     330          96 : }
     331             : #endif
     332             : 
     333             : AudioLayer*
     334          32 : AudioPreference::createAudioLayer()
     335             : {
     336             : #if HAVE_AAUDIO
     337             :     return new AAudioLayer(*this);
     338             : #else
     339             : 
     340             : #if HAVE_JACK
     341             :     if (audioApi_ == JACK_API_STR) {
     342             :         try {
     343             :             if (auto ret = system("jack_lsp > /dev/null"))
     344             :                 throw std::runtime_error("Error running jack_lsp: " + std::to_string(ret));
     345             :             return new JackLayer(*this);
     346             :         } catch (const std::runtime_error& e) {
     347             :             JAMI_ERR("%s", e.what());
     348             : #if HAVE_PULSE
     349             :             audioApi_ = PULSEAUDIO_API_STR;
     350             : #elif HAVE_ALSA
     351             :             audioApi_ = ALSA_API_STR;
     352             : #elif HAVE_COREAUDIO
     353             :             audioApi_ = COREAUDIO_API_STR;
     354             : #elif HAVE_PORTAUDIO
     355             :             audioApi_ = PORTAUDIO_API_STR;
     356             : #else
     357             :             throw;
     358             : #endif // HAVE_PULSE
     359             :         }
     360             :     }
     361             : #endif // HAVE_JACK
     362             : 
     363             : #if HAVE_PULSE
     364             : 
     365          32 :     if (audioApi_ == PULSEAUDIO_API_STR) {
     366             :         try {
     367           3 :             return new PulseLayer(*this);
     368           3 :         } catch (const std::runtime_error& e) {
     369           3 :             JAMI_WARN("Unable to create pulseaudio layer, falling back to ALSA");
     370           3 :         }
     371             :     }
     372             : 
     373             : #endif
     374             : 
     375             : #if HAVE_ALSA
     376             : 
     377          32 :     audioApi_ = ALSA_API_STR;
     378          32 :     checkSoundCard(alsaCardin_, AudioDeviceType::CAPTURE);
     379          32 :     checkSoundCard(alsaCardout_, AudioDeviceType::PLAYBACK);
     380          32 :     checkSoundCard(alsaCardRingtone_, AudioDeviceType::RINGTONE);
     381             : 
     382          32 :     return new AlsaLayer(*this);
     383             : #endif
     384             : 
     385             : #if HAVE_COREAUDIO
     386             :     audioApi_ = COREAUDIO_API_STR;
     387             :     try {
     388             :         return new CoreLayer(*this);
     389             :     } catch (const std::runtime_error& e) {
     390             :         JAMI_WARN("Unable to create coreaudio layer. There will be no sound.");
     391             :     }
     392             :     return NULL;
     393             : #endif
     394             : 
     395             : #if HAVE_PORTAUDIO
     396             :     audioApi_ = PORTAUDIO_API_STR;
     397             :     try {
     398             :         return new PortAudioLayer(*this);
     399             :     } catch (const std::runtime_error& e) {
     400             :         JAMI_WARN("Unable to create PortAudio layer. There will be no sound.");
     401             :     }
     402             :     return nullptr;
     403             : #endif
     404             : #endif // HAVE_AAUDIO
     405             : 
     406             :     JAMI_WARN("No audio layer provided");
     407             :     return nullptr;
     408             : }
     409             : 
     410             : std::vector<std::string>
     411           0 : AudioPreference::getSupportedAudioManagers()
     412             : {
     413             :     return {
     414             : #if HAVE_AAUDIO
     415             :         AAUDIO_API_STR,
     416             : #endif
     417             : #if HAVE_ALSA
     418             :         ALSA_API_STR,
     419             : #endif
     420             : #if HAVE_PULSE
     421             :         PULSEAUDIO_API_STR,
     422             : #endif
     423             : #if HAVE_JACK
     424             :         JACK_API_STR,
     425             : #endif
     426             : #if HAVE_COREAUDIO
     427             :         COREAUDIO_API_STR,
     428             : #endif
     429             : #if HAVE_PORTAUDIO
     430             :         PORTAUDIO_API_STR,
     431             : #endif
     432           0 :     };
     433             : }
     434             : 
     435             : void
     436        2449 : AudioPreference::serialize(YAML::Emitter& out) const
     437             : {
     438        2449 :     out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap;
     439             :     // alsa submap
     440        2449 :     out << YAML::Key << ALSAMAP_KEY << YAML::Value << YAML::BeginMap;
     441        2449 :     out << YAML::Key << CARDIN_KEY << YAML::Value << alsaCardin_;
     442        2449 :     out << YAML::Key << CARDOUT_KEY << YAML::Value << alsaCardout_;
     443        2449 :     out << YAML::Key << CARLIBJAMI_KEY << YAML::Value << alsaCardRingtone_;
     444        2449 :     out << YAML::Key << PLUGIN_KEY << YAML::Value << alsaPlugin_;
     445        2449 :     out << YAML::Key << SMPLRATE_KEY << YAML::Value << alsaSmplrate_;
     446        2449 :     out << YAML::EndMap;
     447             : 
     448             :     // common options
     449        2449 :     out << YAML::Key << ALWAYS_RECORDING_KEY << YAML::Value << alwaysRecording_;
     450        2449 :     out << YAML::Key << AUDIO_API_KEY << YAML::Value << audioApi_;
     451        2449 :     out << YAML::Key << CAPTURE_MUTED_KEY << YAML::Value << captureMuted_;
     452        2449 :     out << YAML::Key << PLAYBACK_MUTED_KEY << YAML::Value << playbackMuted_;
     453             : 
     454             :     // pulse submap
     455        2449 :     out << YAML::Key << PULSEMAP_KEY << YAML::Value << YAML::BeginMap;
     456        2449 :     out << YAML::Key << DEVICE_PLAYBACK_KEY << YAML::Value << pulseDevicePlayback_;
     457        2449 :     out << YAML::Key << DEVICE_RECORD_KEY << YAML::Value << pulseDeviceRecord_;
     458        2449 :     out << YAML::Key << DEVICE_RINGTONE_KEY << YAML::Value << pulseDeviceRingtone_;
     459        2449 :     out << YAML::EndMap;
     460             : 
     461             :     // portaudio submap
     462        2449 :     out << YAML::Key << PORTAUDIO_KEY << YAML::Value << YAML::BeginMap;
     463        2449 :     out << YAML::Key << DEVICE_PLAYBACK_KEY << YAML::Value << portaudioDevicePlayback_;
     464        2449 :     out << YAML::Key << DEVICE_RECORD_KEY << YAML::Value << portaudioDeviceRecord_;
     465        2449 :     out << YAML::Key << DEVICE_RINGTONE_KEY << YAML::Value << portaudioDeviceRingtone_;
     466        2449 :     out << YAML::EndMap;
     467             : 
     468             :     // more common options!
     469        2449 :     out << YAML::Key << RECORDPATH_KEY << YAML::Value << recordpath_;
     470        2449 :     out << YAML::Key << VOLUMEMIC_KEY << YAML::Value << volumemic_;
     471        2449 :     out << YAML::Key << VOLUMESPKR_KEY << YAML::Value << volumespkr_;
     472             : 
     473             :     // audio processor options, not in a submap
     474        2449 :     out << YAML::Key << AUDIO_PROCESSOR_KEY << YAML::Value << audioProcessor_;
     475        2449 :     out << YAML::Key << AGC_KEY << YAML::Value << agcEnabled_;
     476        2449 :     out << YAML::Key << VAD_KEY << YAML::Value << vadEnabled_;
     477        2449 :     out << YAML::Key << NOISE_REDUCE_KEY << YAML::Value << denoise_;
     478        2449 :     out << YAML::Key << ECHO_CANCEL_KEY << YAML::Value << echoCanceller_;
     479        2449 :     out << YAML::EndMap;
     480        2449 : }
     481             : 
     482             : bool
     483           0 : AudioPreference::setRecordPath(const std::string& r)
     484             : {
     485           0 :     std::string path = fileutils::expand_path(r);
     486           0 :     if (fileutils::isDirectoryWritable(path)) {
     487           0 :         recordpath_ = path;
     488           0 :         return true;
     489             :     } else {
     490           0 :         JAMI_ERR("%s is not writable, unable to be the recording path", path.c_str());
     491           0 :         return false;
     492             :     }
     493           0 : }
     494             : 
     495             : void
     496          29 : AudioPreference::unserialize(const YAML::Node& in)
     497             : {
     498          29 :     const auto& node = in[CONFIG_LABEL];
     499             : 
     500             :     // alsa submap
     501          29 :     const auto& alsa = node[ALSAMAP_KEY];
     502             : 
     503          29 :     parseValue(alsa, CARDIN_KEY, alsaCardin_);
     504          29 :     parseValue(alsa, CARDOUT_KEY, alsaCardout_);
     505          29 :     parseValue(alsa, CARLIBJAMI_KEY, alsaCardRingtone_);
     506          29 :     parseValue(alsa, PLUGIN_KEY, alsaPlugin_);
     507          29 :     parseValue(alsa, SMPLRATE_KEY, alsaSmplrate_);
     508             : 
     509             :     // common options
     510          29 :     parseValue(node, ALWAYS_RECORDING_KEY, alwaysRecording_);
     511          29 :     parseValue(node, AUDIO_API_KEY, audioApi_);
     512          29 :     parseValue(node, AGC_KEY, agcEnabled_);
     513          29 :     parseValue(node, CAPTURE_MUTED_KEY, captureMuted_);
     514          29 :     parseValue(node, NOISE_REDUCE_KEY, denoise_);
     515          29 :     parseValue(node, PLAYBACK_MUTED_KEY, playbackMuted_);
     516             : 
     517             :     // pulse submap
     518          29 :     const auto& pulse = node[PULSEMAP_KEY];
     519          29 :     parseValue(pulse, DEVICE_PLAYBACK_KEY, pulseDevicePlayback_);
     520          29 :     parseValue(pulse, DEVICE_RECORD_KEY, pulseDeviceRecord_);
     521          29 :     parseValue(pulse, DEVICE_RINGTONE_KEY, pulseDeviceRingtone_);
     522             : 
     523             :     // portaudio submap
     524          29 :     const auto& portaudio = node[PORTAUDIO_KEY];
     525          29 :     parseValue(portaudio, DEVICE_PLAYBACK_KEY, portaudioDevicePlayback_);
     526          29 :     parseValue(portaudio, DEVICE_RECORD_KEY, portaudioDeviceRecord_);
     527          29 :     parseValue(portaudio, DEVICE_RINGTONE_KEY, portaudioDeviceRingtone_);
     528             : 
     529             :     // more common options!
     530          29 :     parseValue(node, RECORDPATH_KEY, recordpath_);
     531          29 :     parseValue(node, VOLUMEMIC_KEY, volumemic_);
     532          29 :     parseValue(node, VOLUMESPKR_KEY, volumespkr_);
     533          29 :     parseValue(node, AUDIO_PROCESSOR_KEY, audioProcessor_);
     534          29 :     parseValue(node, VAD_KEY, vadEnabled_);
     535          29 :     parseValue(node, ECHO_CANCEL_KEY, echoCanceller_);
     536          29 : }
     537             : 
     538             : #ifdef ENABLE_VIDEO
     539          38 : VideoPreferences::VideoPreferences()
     540          38 :     : decodingAccelerated_(true)
     541          38 :     , encodingAccelerated_(false)
     542          38 :     , recordPreview_(true)
     543          38 :     , recordQuality_(0)
     544          38 :     , conferenceResolution_(DEFAULT_CONFERENCE_RESOLUTION)
     545          38 : {}
     546             : 
     547             : void
     548        2449 : VideoPreferences::serialize(YAML::Emitter& out) const
     549             : {
     550        2449 :     out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap;
     551        2449 :     out << YAML::Key << RECORD_PREVIEW_KEY << YAML::Value << recordPreview_;
     552        2449 :     out << YAML::Key << RECORD_QUALITY_KEY << YAML::Value << recordQuality_;
     553             : #ifdef ENABLE_HWACCEL
     554        2449 :     out << YAML::Key << DECODING_ACCELERATED_KEY << YAML::Value << decodingAccelerated_;
     555        2449 :     out << YAML::Key << ENCODING_ACCELERATED_KEY << YAML::Value << encodingAccelerated_;
     556             : #endif
     557        2449 :     out << YAML::Key << CONFERENCE_RESOLUTION_KEY << YAML::Value << conferenceResolution_;
     558        2449 :     if (auto* dm = getVideoDeviceMonitor())
     559        2443 :         dm->serialize(out);
     560        2449 :     out << YAML::EndMap;
     561        2449 : }
     562             : 
     563             : void
     564          29 : VideoPreferences::unserialize(const YAML::Node& in)
     565             : {
     566             :     // values may or may not be present
     567          29 :     const auto& node = in[CONFIG_LABEL];
     568             :     try {
     569          29 :         parseValue(node, RECORD_PREVIEW_KEY, recordPreview_);
     570          29 :         parseValue(node, RECORD_QUALITY_KEY, recordQuality_);
     571           0 :     } catch (...) {
     572           0 :         recordPreview_ = true;
     573           0 :         recordQuality_ = 0;
     574           0 :     }
     575             : #ifdef ENABLE_HWACCEL
     576             :     try {
     577          29 :         parseValue(node, DECODING_ACCELERATED_KEY, decodingAccelerated_);
     578          29 :         parseValue(node, ENCODING_ACCELERATED_KEY, encodingAccelerated_);
     579           0 :     } catch (...) {
     580           0 :         decodingAccelerated_ = true;
     581           0 :         encodingAccelerated_ = false;
     582           0 :     }
     583             : #endif
     584             :     try {
     585          29 :         parseValue(node, CONFERENCE_RESOLUTION_KEY, conferenceResolution_);
     586           0 :     } catch (...) {
     587           0 :         conferenceResolution_ = DEFAULT_CONFERENCE_RESOLUTION;
     588           0 :     }
     589          29 :     if (auto* dm = getVideoDeviceMonitor())
     590          29 :         dm->unserialize(in);
     591          29 : }
     592             : #endif // ENABLE_VIDEO
     593             : 
     594             : #ifdef ENABLE_PLUGIN
     595          38 : PluginPreferences::PluginPreferences()
     596          38 :     : pluginsEnabled_(false)
     597          38 : {}
     598             : 
     599             : void
     600        2449 : PluginPreferences::serialize(YAML::Emitter& out) const
     601             : {
     602        2449 :     out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap;
     603        2449 :     out << YAML::Key << JAMI_PLUGIN_KEY << YAML::Value << pluginsEnabled_;
     604        2449 :     out << YAML::Key << JAMI_PLUGINS_INSTALLED_KEY << YAML::Value << installedPlugins_;
     605        2449 :     out << YAML::Key << JAMI_PLUGINS_LOADED_KEY << YAML::Value << loadedPlugins_;
     606        2449 :     out << YAML::EndMap;
     607        2449 : }
     608             : 
     609             : void
     610          29 : PluginPreferences::unserialize(const YAML::Node& in)
     611             : {
     612             :     // values may or may not be present
     613          29 :     const auto& node = in[CONFIG_LABEL];
     614             :     try {
     615          29 :         parseValue(node, JAMI_PLUGIN_KEY, pluginsEnabled_);
     616           0 :     } catch (...) {
     617           0 :         pluginsEnabled_ = false;
     618           0 :     }
     619             : 
     620          29 :     const auto& installedPluginsNode = node[JAMI_PLUGINS_INSTALLED_KEY];
     621             :     try {
     622          29 :         installedPlugins_ = yaml_utils::parseVector(installedPluginsNode);
     623           0 :     } catch (const std::exception& e) {
     624           0 :         JAMI_WARNING("Couldn't parse vector of installed plugins: {}", e.what());
     625           0 :     }
     626             : 
     627          29 :     const auto& loadedPluginsNode = node[JAMI_PLUGINS_LOADED_KEY];
     628             :     try {
     629          29 :         loadedPlugins_ = yaml_utils::parseVector(loadedPluginsNode);
     630           0 :     } catch (const std::exception& e) {
     631           0 :         JAMI_WARNING("Couldn't parse vector of loaded plugins: {}", e.what());
     632           0 :     }
     633          29 : }
     634             : #endif // ENABLE_PLUGIN
     635             : 
     636             : } // namespace jami

Generated by: LCOV version 1.14